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.
@@ -4,7 +4,8 @@
4
4
  "Bash(npm run build:prod:*)",
5
5
  "Bash(node:*)",
6
6
  "Bash(npx tsc:*)",
7
- "Bash(find:*)"
7
+ "Bash(find:*)",
8
+ "Bash(rm:*)"
8
9
  ],
9
10
  "deny": []
10
11
  }
@@ -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, throw an error
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
+ };