at-builder 1.2.2 → 1.2.3
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/settings.local.json +2 -1
- package/bin/constants/config.js +53 -0
- package/bin/index.js +76 -1
- package/bin/services/doctor.js +346 -0
- package/lib/at-deploy.js +309 -0
- package/package.json +6 -4
- package/src/constants/config.ts +55 -0
- package/src/index.ts +86 -1
- package/src/services/doctor.ts +383 -0
- package/test-validation.js +21 -0
- package/tsconfig.json +1 -1
- package/webpack.config.js +34 -1
package/bin/constants/config.js
CHANGED
|
@@ -71,6 +71,10 @@ ${formatText("COMMANDS", 'yellow', true)}
|
|
|
71
71
|
${formatText("build --prod", 'cyan', true)} Build for production deployment
|
|
72
72
|
${formatText("dev", 'cyan', true)} Start development server with file watching
|
|
73
73
|
${formatText("dev --browser", 'cyan', true)} Start development server and open in browser
|
|
74
|
+
${formatText("deploy", 'cyan', true)} Deploy activity to Adobe Target
|
|
75
|
+
${formatText("deploy --dry-run", 'cyan', true)} Deploy in dry-run mode without actual deployment
|
|
76
|
+
${formatText("doctor", 'cyan', true)} Diagnose and fix project configuration issues
|
|
77
|
+
${formatText("doctor --fix", 'cyan', true)} Automatically fix detected configuration issues
|
|
74
78
|
|
|
75
79
|
${formatText("GLOBAL OPTIONS", 'yellow', true)}
|
|
76
80
|
${formatText("-v, --verbose", 'green')} Enable detailed logging
|
|
@@ -92,6 +96,18 @@ ${formatText("EXAMPLES", 'yellow', true)}
|
|
|
92
96
|
|
|
93
97
|
${formatText("# Development server with browser", 'gray')}
|
|
94
98
|
${formatText("atb dev --browser", 'white')}
|
|
99
|
+
|
|
100
|
+
${formatText("# Deploy to Adobe Target", 'gray')}
|
|
101
|
+
${formatText("atb deploy", 'white')}
|
|
102
|
+
|
|
103
|
+
${formatText("# Deploy in dry-run mode", 'gray')}
|
|
104
|
+
${formatText("atb deploy --dry-run", 'white')}
|
|
105
|
+
|
|
106
|
+
${formatText("# Check project configuration", 'gray')}
|
|
107
|
+
${formatText("atb doctor", 'white')}
|
|
108
|
+
|
|
109
|
+
${formatText("# Auto-fix configuration issues", 'gray')}
|
|
110
|
+
${formatText("atb doctor --fix", 'white')}
|
|
95
111
|
|
|
96
112
|
${formatText("WORKFLOW", 'yellow', true)}
|
|
97
113
|
${formatText("1.", 'cyan')} Run ${formatText("atb init", 'white')} to set up project configuration
|
|
@@ -99,6 +115,7 @@ ${formatText("WORKFLOW", 'yellow', true)}
|
|
|
99
115
|
${formatText("3.", 'cyan')} Develop variations in ${formatText("/Activities/{name}/Variation-*/", 'gray')}
|
|
100
116
|
${formatText("4.", 'cyan')} Run ${formatText("atb build", 'white')} for development testing
|
|
101
117
|
${formatText("5.", 'cyan')} Run ${formatText("atb build --prod", 'white')} for Adobe Target deployment
|
|
118
|
+
${formatText("6.", 'cyan')} Run ${formatText("atb deploy", 'white')} to deploy to Adobe Target
|
|
102
119
|
|
|
103
120
|
${formatText("SUPPORT", 'yellow', true)}
|
|
104
121
|
Repository: ${formatText("https://github.com/upesenga/at-builder", 'blue')}
|
|
@@ -114,6 +131,7 @@ const setupEnv = async (basePath) => {
|
|
|
114
131
|
if (!fs_1.default.existsSync(envPath)) {
|
|
115
132
|
// Define the content of the .env file
|
|
116
133
|
const envContent = `
|
|
134
|
+
ACTIVITIES_BASE_FOLDER="Activities"
|
|
117
135
|
ACTIVITY_FOLDER_NAME=""
|
|
118
136
|
PUPPETEER_LANDING_PAGE=""
|
|
119
137
|
TARGET_URL=""
|
|
@@ -121,6 +139,10 @@ LOGIN_URL=""
|
|
|
121
139
|
VARIATION="Variation-1"
|
|
122
140
|
NODE_ENV="development"
|
|
123
141
|
VERBOSE=false
|
|
142
|
+
|
|
143
|
+
# Adobe Target Deployment Configuration
|
|
144
|
+
ADOBE_CLIENT_ID=""
|
|
145
|
+
ADOBE_CLIENT_SECRET=""
|
|
124
146
|
`;
|
|
125
147
|
// Write the content to the .env file
|
|
126
148
|
fs_1.default.writeFileSync(envPath, envContent.trim(), 'utf8');
|
|
@@ -130,6 +152,7 @@ VERBOSE=false
|
|
|
130
152
|
console.log('.env file already exists!');
|
|
131
153
|
}
|
|
132
154
|
createWatchConfig(basePath);
|
|
155
|
+
createAdobeConfig(basePath);
|
|
133
156
|
};
|
|
134
157
|
exports.setupEnv = setupEnv;
|
|
135
158
|
const createWatchConfig = (basePath) => {
|
|
@@ -148,6 +171,36 @@ const createWatchConfig = (basePath) => {
|
|
|
148
171
|
console.log('watch-config.json file already exists!');
|
|
149
172
|
}
|
|
150
173
|
};
|
|
174
|
+
const createAdobeConfig = (basePath) => {
|
|
175
|
+
// Path to the adobe.config.js file
|
|
176
|
+
const adobeConfigPath = path_1.default.join(basePath, 'adobe.config.js');
|
|
177
|
+
// Default content for adobe.config.js
|
|
178
|
+
const adobeConfigContent = `/**
|
|
179
|
+
* Adobe Target API Configuration
|
|
180
|
+
*
|
|
181
|
+
* Configuration constants for Adobe Target API integration.
|
|
182
|
+
* These values are used by the deployment script to connect to Adobe Target.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
module.exports = {
|
|
186
|
+
// Adobe Target API base URL
|
|
187
|
+
BASE_URL: 'https://mc.adobe.io/target/activities/',
|
|
188
|
+
|
|
189
|
+
// Adobe IMS (Identity Management Services) token endpoint
|
|
190
|
+
IMS_TOKEN_URL: 'https://ims-na1.adobelogin.com/ims/token/v1',
|
|
191
|
+
|
|
192
|
+
// Required scopes for Adobe Target API access
|
|
193
|
+
IMS_SCOPE: 'openid,target_sdk'
|
|
194
|
+
};`;
|
|
195
|
+
// Check if the adobe.config.js file already exists
|
|
196
|
+
if (!fs_1.default.existsSync(adobeConfigPath)) {
|
|
197
|
+
fs_1.default.writeFileSync(adobeConfigPath, adobeConfigContent, 'utf8');
|
|
198
|
+
console.log('adobe.config.js file created successfully!');
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.log('adobe.config.js file already exists!');
|
|
202
|
+
}
|
|
203
|
+
};
|
|
151
204
|
/**
|
|
152
205
|
* Reads and returns environment variables from the specified .env file
|
|
153
206
|
* @param {string} basePath - The base path where the .env file is located
|
package/bin/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const commander_1 = require("commander");
|
|
11
11
|
const config_1 = require("./constants/config");
|
|
12
|
+
const doctor_1 = require("./services/doctor");
|
|
12
13
|
const logger_1 = __importDefault(require("./services/logger"));
|
|
13
14
|
/**
|
|
14
15
|
* Checks if the .env file exists at the current working directory
|
|
@@ -23,7 +24,9 @@ const checkEnvFile = () => {
|
|
|
23
24
|
logger_1.default.info("checkEnvFile", ".env file found");
|
|
24
25
|
}
|
|
25
26
|
catch (error) {
|
|
26
|
-
// If the file does not exist,
|
|
27
|
+
// If the file does not exist, provide helpful guidance
|
|
28
|
+
console.error('\x1b[31m%s\x1b[0m', `❌ Error: .env file not found at ${process.cwd()}`);
|
|
29
|
+
console.error('\x1b[33m%s\x1b[0m', '💡 Run "atb init" to create .env file or "atb doctor --fix" to diagnose and fix configuration issues.');
|
|
27
30
|
logger_1.default.error("checkEnvFile", `Error: Couldn't find .env file at location ${process.cwd()}`);
|
|
28
31
|
throw error;
|
|
29
32
|
}
|
|
@@ -76,6 +79,23 @@ const setupCommander = async () => {
|
|
|
76
79
|
checkEnvFile();
|
|
77
80
|
await handleDev(options.browser, globalOpts.verbose);
|
|
78
81
|
});
|
|
82
|
+
program
|
|
83
|
+
.command('deploy')
|
|
84
|
+
.description('Deploy activity to Adobe Target using at-deploy.js')
|
|
85
|
+
.option('--dry-run', 'Run deployment in dry-run mode without actual deployment')
|
|
86
|
+
.action(async (options, command) => {
|
|
87
|
+
const globalOpts = command.parent.opts();
|
|
88
|
+
checkEnvFile();
|
|
89
|
+
await handleDeploy(options.dryRun, globalOpts.verbose);
|
|
90
|
+
});
|
|
91
|
+
program
|
|
92
|
+
.command('doctor')
|
|
93
|
+
.description('Diagnose and fix project configuration issues')
|
|
94
|
+
.option('--fix', 'Automatically fix detected issues')
|
|
95
|
+
.action(async (options, command) => {
|
|
96
|
+
const globalOpts = command.parent.opts();
|
|
97
|
+
await handleDoctor(options.fix, globalOpts.verbose);
|
|
98
|
+
});
|
|
79
99
|
await program.parseAsync(process.argv);
|
|
80
100
|
logger_1.default.info("setupCommander", "Commander setup complete");
|
|
81
101
|
};
|
|
@@ -153,6 +173,61 @@ const handleDev = async (browser, verbose) => {
|
|
|
153
173
|
logger_1.default.info("handleDev", `Running command: ${commandArr.join(', ')}`);
|
|
154
174
|
runCommand(commandArr, productionEnv);
|
|
155
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* Handles the deploy command
|
|
178
|
+
*/
|
|
179
|
+
const handleDeploy = async (dryRun, verbose) => {
|
|
180
|
+
if (verbose)
|
|
181
|
+
logger_1.default.info("verbose", `Deploying to Adobe Target with dry-run=${dryRun}`);
|
|
182
|
+
logger_1.default.info("handleDeploy", "Running Adobe Target deployment");
|
|
183
|
+
// Set environment variables for the deployment script
|
|
184
|
+
const deployEnv = {
|
|
185
|
+
...productionEnv,
|
|
186
|
+
VERBOSE: verbose.toString(),
|
|
187
|
+
DRY_RUN: dryRun.toString()
|
|
188
|
+
};
|
|
189
|
+
// Run the at-deploy.js script
|
|
190
|
+
runCommand(['run', 'deploy'], deployEnv);
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Handles the doctor command
|
|
194
|
+
*/
|
|
195
|
+
const handleDoctor = async (autoFix, verbose) => {
|
|
196
|
+
if (verbose)
|
|
197
|
+
logger_1.default.info("verbose", `Running diagnostics with auto-fix=${autoFix}`);
|
|
198
|
+
logger_1.default.info("handleDoctor", "Diagnosing project configuration");
|
|
199
|
+
try {
|
|
200
|
+
// Run diagnostics
|
|
201
|
+
const issues = await (0, doctor_1.runDiagnostics)(process.cwd(), verbose);
|
|
202
|
+
if (issues.length === 0) {
|
|
203
|
+
console.log("✅ No issues found. Your project configuration is healthy!");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Display issues
|
|
207
|
+
console.log(`\n🔍 Found ${issues.length} issue(s):\n`);
|
|
208
|
+
issues.forEach((issue, index) => {
|
|
209
|
+
console.log(`${index + 1}. ${issue.severity === 'error' ? '❌' : '⚠️'} ${issue.message}`);
|
|
210
|
+
if (issue.suggestion) {
|
|
211
|
+
console.log(` 💡 ${issue.suggestion}`);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
if (autoFix) {
|
|
215
|
+
console.log('\n🔧 Attempting to fix issues...\n');
|
|
216
|
+
const fixed = await (0, doctor_1.fixIssues)(issues, process.cwd(), verbose);
|
|
217
|
+
console.log(`\n✅ Fixed ${fixed} issue(s).`);
|
|
218
|
+
if (fixed < issues.length) {
|
|
219
|
+
console.log(`⚠️ ${issues.length - fixed} issue(s) require manual attention.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.log('\n💡 Run `atb doctor --fix` to automatically fix resolvable issues.');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
logger_1.default.error("handleDoctor", `Doctor command failed: ${error.message}`);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
156
231
|
// Command execution logic
|
|
157
232
|
/**
|
|
158
233
|
* Main command execution entry point
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fixIssues = exports.runDiagnostics = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
10
|
+
/**
|
|
11
|
+
* Run comprehensive diagnostics on the project
|
|
12
|
+
*/
|
|
13
|
+
const runDiagnostics = async (projectPath, verbose = false) => {
|
|
14
|
+
const issues = [];
|
|
15
|
+
if (verbose)
|
|
16
|
+
logger_1.default.info("runDiagnostics", `Running diagnostics on ${projectPath}`);
|
|
17
|
+
// Check for required files
|
|
18
|
+
await checkEnvFile(projectPath, issues);
|
|
19
|
+
await checkAdobeConfig(projectPath, issues);
|
|
20
|
+
await checkWatchConfig(projectPath, issues);
|
|
21
|
+
await checkPackageJson(projectPath, issues);
|
|
22
|
+
await checkActivitiesFolder(projectPath, issues);
|
|
23
|
+
// Check environment variables
|
|
24
|
+
await checkEnvVariables(projectPath, issues);
|
|
25
|
+
// Check dependencies
|
|
26
|
+
await checkDependencies(projectPath, issues);
|
|
27
|
+
return issues;
|
|
28
|
+
};
|
|
29
|
+
exports.runDiagnostics = runDiagnostics;
|
|
30
|
+
/**
|
|
31
|
+
* Attempt to fix the provided issues
|
|
32
|
+
*/
|
|
33
|
+
const fixIssues = async (issues, projectPath, verbose = false) => {
|
|
34
|
+
let fixedCount = 0;
|
|
35
|
+
for (const issue of issues) {
|
|
36
|
+
if (!issue.fixable)
|
|
37
|
+
continue;
|
|
38
|
+
try {
|
|
39
|
+
if (verbose)
|
|
40
|
+
logger_1.default.info("fixIssues", `Attempting to fix: ${issue.id}`);
|
|
41
|
+
const success = await fixIssue(issue, projectPath, verbose);
|
|
42
|
+
if (success) {
|
|
43
|
+
console.log(`✅ Fixed: ${issue.message}`);
|
|
44
|
+
fixedCount++;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(`❌ Could not fix: ${issue.message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.log(`❌ Error fixing ${issue.id}: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return fixedCount;
|
|
55
|
+
};
|
|
56
|
+
exports.fixIssues = fixIssues;
|
|
57
|
+
/**
|
|
58
|
+
* Fix a specific issue
|
|
59
|
+
*/
|
|
60
|
+
const fixIssue = async (issue, projectPath, verbose) => {
|
|
61
|
+
switch (issue.id) {
|
|
62
|
+
case 'missing-env':
|
|
63
|
+
return await createEnvFile(projectPath);
|
|
64
|
+
case 'missing-adobe-config':
|
|
65
|
+
return await createAdobeConfig(projectPath);
|
|
66
|
+
case 'missing-watch-config':
|
|
67
|
+
return await createWatchConfig(projectPath);
|
|
68
|
+
case 'missing-activities-folder':
|
|
69
|
+
return await createActivitiesFolder(projectPath);
|
|
70
|
+
case 'missing-package-json':
|
|
71
|
+
return await createPackageJson(projectPath);
|
|
72
|
+
default:
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Check if .env file exists and has required variables
|
|
78
|
+
*/
|
|
79
|
+
const checkEnvFile = async (projectPath, issues) => {
|
|
80
|
+
const envPath = path_1.default.join(projectPath, '.env');
|
|
81
|
+
if (!fs_1.default.existsSync(envPath)) {
|
|
82
|
+
issues.push({
|
|
83
|
+
id: 'missing-env',
|
|
84
|
+
severity: 'error',
|
|
85
|
+
message: '.env file is missing',
|
|
86
|
+
suggestion: 'Create .env file with required environment variables',
|
|
87
|
+
fixable: true,
|
|
88
|
+
file: '.env'
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Check if .env has required variables
|
|
93
|
+
const envContent = fs_1.default.readFileSync(envPath, 'utf8');
|
|
94
|
+
const requiredVars = [
|
|
95
|
+
'ACTIVITIES_BASE_FOLDER',
|
|
96
|
+
'ACTIVITY_FOLDER_NAME',
|
|
97
|
+
'ADOBE_CLIENT_ID',
|
|
98
|
+
'ADOBE_CLIENT_SECRET'
|
|
99
|
+
];
|
|
100
|
+
const missingVars = requiredVars.filter(varName => !envContent.includes(varName));
|
|
101
|
+
if (missingVars.length > 0) {
|
|
102
|
+
issues.push({
|
|
103
|
+
id: 'incomplete-env',
|
|
104
|
+
severity: 'warning',
|
|
105
|
+
message: `.env file missing variables: ${missingVars.join(', ')}`,
|
|
106
|
+
suggestion: 'Add missing environment variables to .env file',
|
|
107
|
+
fixable: true,
|
|
108
|
+
file: '.env'
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Check if adobe.config.js exists
|
|
114
|
+
*/
|
|
115
|
+
const checkAdobeConfig = async (projectPath, issues) => {
|
|
116
|
+
const configPath = path_1.default.join(projectPath, 'adobe.config.js');
|
|
117
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
118
|
+
issues.push({
|
|
119
|
+
id: 'missing-adobe-config',
|
|
120
|
+
severity: 'error',
|
|
121
|
+
message: 'adobe.config.js file is missing',
|
|
122
|
+
suggestion: 'Create Adobe Target API configuration file',
|
|
123
|
+
fixable: true,
|
|
124
|
+
file: 'adobe.config.js'
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Check if watch-config.json exists
|
|
130
|
+
*/
|
|
131
|
+
const checkWatchConfig = async (projectPath, issues) => {
|
|
132
|
+
const configPath = path_1.default.join(projectPath, 'watch-config.json');
|
|
133
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
134
|
+
issues.push({
|
|
135
|
+
id: 'missing-watch-config',
|
|
136
|
+
severity: 'warning',
|
|
137
|
+
message: 'watch-config.json file is missing',
|
|
138
|
+
suggestion: 'Create build configuration file',
|
|
139
|
+
fixable: true,
|
|
140
|
+
file: 'watch-config.json'
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Check if package.json exists
|
|
146
|
+
*/
|
|
147
|
+
const checkPackageJson = async (projectPath, issues) => {
|
|
148
|
+
const packagePath = path_1.default.join(projectPath, 'package.json');
|
|
149
|
+
if (!fs_1.default.existsSync(packagePath)) {
|
|
150
|
+
issues.push({
|
|
151
|
+
id: 'missing-package-json',
|
|
152
|
+
severity: 'error',
|
|
153
|
+
message: 'package.json file is missing',
|
|
154
|
+
suggestion: 'Initialize npm project with package.json',
|
|
155
|
+
fixable: true,
|
|
156
|
+
file: 'package.json'
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Check if Activities folder exists
|
|
162
|
+
*/
|
|
163
|
+
const checkActivitiesFolder = async (projectPath, issues) => {
|
|
164
|
+
// Try to read ACTIVITIES_BASE_FOLDER from .env, fallback to default
|
|
165
|
+
let activitiesFolder = 'Activities';
|
|
166
|
+
const envPath = path_1.default.join(projectPath, '.env');
|
|
167
|
+
if (fs_1.default.existsSync(envPath)) {
|
|
168
|
+
const envContent = fs_1.default.readFileSync(envPath, 'utf8');
|
|
169
|
+
const match = envContent.match(/ACTIVITIES_BASE_FOLDER=["']?([^"'\n\r]+)["']?/);
|
|
170
|
+
if (match) {
|
|
171
|
+
activitiesFolder = match[1];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const activitiesPath = path_1.default.join(projectPath, activitiesFolder);
|
|
175
|
+
if (!fs_1.default.existsSync(activitiesPath)) {
|
|
176
|
+
issues.push({
|
|
177
|
+
id: 'missing-activities-folder',
|
|
178
|
+
severity: 'warning',
|
|
179
|
+
message: `${activitiesFolder} folder is missing`,
|
|
180
|
+
suggestion: `Create ${activitiesFolder} folder for your activities`,
|
|
181
|
+
fixable: true,
|
|
182
|
+
file: activitiesFolder
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Check environment variables content
|
|
188
|
+
*/
|
|
189
|
+
const checkEnvVariables = async (projectPath, issues) => {
|
|
190
|
+
const envPath = path_1.default.join(projectPath, '.env');
|
|
191
|
+
if (!fs_1.default.existsSync(envPath))
|
|
192
|
+
return;
|
|
193
|
+
const envContent = fs_1.default.readFileSync(envPath, 'utf8');
|
|
194
|
+
// Check if ACTIVITY_FOLDER_NAME is empty
|
|
195
|
+
if (envContent.includes('ACTIVITY_FOLDER_NAME=""') || envContent.includes('ACTIVITY_FOLDER_NAME=\'\'')) {
|
|
196
|
+
issues.push({
|
|
197
|
+
id: 'empty-activity-folder-name',
|
|
198
|
+
severity: 'warning',
|
|
199
|
+
message: 'ACTIVITY_FOLDER_NAME is empty',
|
|
200
|
+
suggestion: 'Set ACTIVITY_FOLDER_NAME to your activity folder name',
|
|
201
|
+
fixable: false
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Check if Adobe credentials are empty
|
|
205
|
+
if (envContent.includes('ADOBE_CLIENT_ID=""') || envContent.includes('ADOBE_CLIENT_ID=\'\'')) {
|
|
206
|
+
issues.push({
|
|
207
|
+
id: 'empty-adobe-client-id',
|
|
208
|
+
severity: 'warning',
|
|
209
|
+
message: 'ADOBE_CLIENT_ID is empty',
|
|
210
|
+
suggestion: 'Set your Adobe Target API client ID',
|
|
211
|
+
fixable: false
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (envContent.includes('ADOBE_CLIENT_SECRET=""') || envContent.includes('ADOBE_CLIENT_SECRET=\'\'')) {
|
|
215
|
+
issues.push({
|
|
216
|
+
id: 'empty-adobe-client-secret',
|
|
217
|
+
severity: 'warning',
|
|
218
|
+
message: 'ADOBE_CLIENT_SECRET is empty',
|
|
219
|
+
suggestion: 'Set your Adobe Target API client secret',
|
|
220
|
+
fixable: false
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Check dependencies
|
|
226
|
+
*/
|
|
227
|
+
const checkDependencies = async (projectPath, issues) => {
|
|
228
|
+
const packagePath = path_1.default.join(projectPath, 'package.json');
|
|
229
|
+
if (!fs_1.default.existsSync(packagePath))
|
|
230
|
+
return;
|
|
231
|
+
const nodeModulesPath = path_1.default.join(projectPath, 'node_modules');
|
|
232
|
+
if (!fs_1.default.existsSync(nodeModulesPath)) {
|
|
233
|
+
issues.push({
|
|
234
|
+
id: 'missing-node-modules',
|
|
235
|
+
severity: 'warning',
|
|
236
|
+
message: 'node_modules folder is missing',
|
|
237
|
+
suggestion: 'Run "npm install" to install dependencies',
|
|
238
|
+
fixable: false
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
// Fix functions
|
|
243
|
+
const createEnvFile = async (projectPath) => {
|
|
244
|
+
const envPath = path_1.default.join(projectPath, '.env');
|
|
245
|
+
const envContent = `ACTIVITIES_BASE_FOLDER="Activities"
|
|
246
|
+
ACTIVITY_FOLDER_NAME=""
|
|
247
|
+
PUPPETEER_LANDING_PAGE=""
|
|
248
|
+
TARGET_URL=""
|
|
249
|
+
LOGIN_URL=""
|
|
250
|
+
VARIATION="Variation-1"
|
|
251
|
+
NODE_ENV="development"
|
|
252
|
+
VERBOSE=false
|
|
253
|
+
|
|
254
|
+
# Adobe Target Deployment Configuration
|
|
255
|
+
ADOBE_CLIENT_ID=""
|
|
256
|
+
ADOBE_CLIENT_SECRET=""`;
|
|
257
|
+
try {
|
|
258
|
+
fs_1.default.writeFileSync(envPath, envContent, 'utf8');
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const createAdobeConfig = async (projectPath) => {
|
|
266
|
+
const configPath = path_1.default.join(projectPath, 'adobe.config.js');
|
|
267
|
+
const configContent = `/**
|
|
268
|
+
* Adobe Target API Configuration
|
|
269
|
+
*
|
|
270
|
+
* Configuration constants for Adobe Target API integration.
|
|
271
|
+
* These values are used by the deployment script to connect to Adobe Target.
|
|
272
|
+
*/
|
|
273
|
+
|
|
274
|
+
module.exports = {
|
|
275
|
+
// Adobe Target API base URL
|
|
276
|
+
BASE_URL: 'https://mc.adobe.io/target/activities/',
|
|
277
|
+
|
|
278
|
+
// Adobe IMS (Identity Management Services) token endpoint
|
|
279
|
+
IMS_TOKEN_URL: 'https://ims-na1.adobelogin.com/ims/token/v1',
|
|
280
|
+
|
|
281
|
+
// Required scopes for Adobe Target API access
|
|
282
|
+
IMS_SCOPE: 'openid,target_sdk'
|
|
283
|
+
};`;
|
|
284
|
+
try {
|
|
285
|
+
fs_1.default.writeFileSync(configPath, configContent, 'utf8');
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
const createWatchConfig = async (projectPath) => {
|
|
293
|
+
const configPath = path_1.default.join(projectPath, 'watch-config.json');
|
|
294
|
+
const configContent = {
|
|
295
|
+
"VARIATION": "Variation-1"
|
|
296
|
+
};
|
|
297
|
+
try {
|
|
298
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(configContent, null, 2), 'utf8');
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const createActivitiesFolder = async (projectPath) => {
|
|
306
|
+
// Try to read ACTIVITIES_BASE_FOLDER from .env, fallback to default
|
|
307
|
+
let activitiesFolder = 'Activities';
|
|
308
|
+
const envPath = path_1.default.join(projectPath, '.env');
|
|
309
|
+
if (fs_1.default.existsSync(envPath)) {
|
|
310
|
+
const envContent = fs_1.default.readFileSync(envPath, 'utf8');
|
|
311
|
+
const match = envContent.match(/ACTIVITIES_BASE_FOLDER=["']?([^"'\n\r]+)["']?/);
|
|
312
|
+
if (match) {
|
|
313
|
+
activitiesFolder = match[1];
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const activitiesPath = path_1.default.join(projectPath, activitiesFolder);
|
|
317
|
+
try {
|
|
318
|
+
fs_1.default.mkdirSync(activitiesPath, { recursive: true });
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const createPackageJson = async (projectPath) => {
|
|
326
|
+
const packagePath = path_1.default.join(projectPath, 'package.json');
|
|
327
|
+
const packageContent = {
|
|
328
|
+
"name": path_1.default.basename(projectPath),
|
|
329
|
+
"version": "1.0.0",
|
|
330
|
+
"description": "",
|
|
331
|
+
"main": "index.js",
|
|
332
|
+
"scripts": {
|
|
333
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
334
|
+
},
|
|
335
|
+
"keywords": [],
|
|
336
|
+
"author": "",
|
|
337
|
+
"license": "ISC"
|
|
338
|
+
};
|
|
339
|
+
try {
|
|
340
|
+
fs_1.default.writeFileSync(packagePath, JSON.stringify(packageContent, null, 2), 'utf8');
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
};
|