at-builder 1.4.0 β 1.4.1
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 +14 -1
- package/.plop/generators/prompts.js +10 -3
- package/.plop/templates/analytics.hbs +1 -1
- package/.plop/utils/index.js +24 -4
- package/README.md +1 -1
- package/bin/constants/config.js +14 -18
- package/bin/index.js +29 -44
- package/lib/at-deploy.js +2 -3
- package/lib/at-sync.js +2 -3
- package/package.json +1 -7
- package/src/constants/config.ts +28 -30
- package/src/index.ts +24 -13
|
@@ -51,7 +51,20 @@
|
|
|
51
51
|
"Bash(ls -la \"$\\(yarn global bin\\)/atb\")",
|
|
52
52
|
"Bash(ls -la \"$\\(yarn global dir \\)/node_modules/at-builder\")",
|
|
53
53
|
"Bash(git commit -m 'fix: surface ESLint error detail and clean up atb deploy build-failure exit *)",
|
|
54
|
-
"Bash(git commit -m 'fix\\(webpack\\): emit correct `variation=` attribute on at-build.html script tag *)"
|
|
54
|
+
"Bash(git commit -m 'fix\\(webpack\\): emit correct `variation=` attribute on at-build.html script tag *)",
|
|
55
|
+
"Bash(yarn install *)",
|
|
56
|
+
"Bash(git rm *)",
|
|
57
|
+
"Bash(git commit -m 'chore\\(deps\\): drop unused/deprecated deps + migrate qs to URLSearchParams *)",
|
|
58
|
+
"Bash(git commit -m 'fix\\(config\\): stop printing red \"Error reading .env\" on every atb invocation *)",
|
|
59
|
+
"Bash(yarn why *)",
|
|
60
|
+
"Bash(git commit -m 'fix\\(plop\\): trim whitespace on all atb new text prompts *)",
|
|
61
|
+
"Bash(atb install-extension *)",
|
|
62
|
+
"Bash(git commit -m 'feat\\(install-extension\\): first-class support for Antigravity IDE \\(agy\\) *)",
|
|
63
|
+
"Bash(npm whoami *)",
|
|
64
|
+
"Bash(npm view *)",
|
|
65
|
+
"Bash(git tag *)",
|
|
66
|
+
"Bash(git push *)",
|
|
67
|
+
"Bash(npm publish *)"
|
|
55
68
|
]
|
|
56
69
|
}
|
|
57
70
|
}
|
|
@@ -19,6 +19,11 @@ const prompts = function (inquirer) {
|
|
|
19
19
|
console.log(kleur.cyan().bold(' π§ͺ Create a new Adobe Target activity'));
|
|
20
20
|
console.log(kleur.gray(' β scaffolds variation folders + shared/build.config.json\n'));
|
|
21
21
|
|
|
22
|
+
// All text inputs go through the same trim filter so downstream code never
|
|
23
|
+
// has to deal with stray leading/trailing whitespace (which would otherwise
|
|
24
|
+
// become folder names with trailing spaces, etc.).
|
|
25
|
+
const trim = (input) => (input || '').trim();
|
|
26
|
+
|
|
22
27
|
return inquirer.prompt([
|
|
23
28
|
{
|
|
24
29
|
type: PROMPT_TYPE_LIST,
|
|
@@ -35,7 +40,8 @@ const prompts = function (inquirer) {
|
|
|
35
40
|
name: 'testName',
|
|
36
41
|
prefix: kleur.cyan('βΊ'),
|
|
37
42
|
message: ask('Activity name', 'folder name, e.g. TEST-1234 hero-banner'),
|
|
38
|
-
|
|
43
|
+
filter: trim,
|
|
44
|
+
validate: (input) => input
|
|
39
45
|
? true
|
|
40
46
|
: 'Activity name cannot be empty.'
|
|
41
47
|
},
|
|
@@ -46,7 +52,8 @@ const prompts = function (inquirer) {
|
|
|
46
52
|
message: (answers) => answers.activityType === 'xt'
|
|
47
53
|
? ask('How many experiences?')
|
|
48
54
|
: ask('How many variations?', 'control is added automatically'),
|
|
49
|
-
|
|
55
|
+
filter: trim,
|
|
56
|
+
validate: (input) => /^[1-9]\d*$/.test(input)
|
|
50
57
|
? true
|
|
51
58
|
: 'Enter a positive integer (1, 2, 3, ...).'
|
|
52
59
|
},
|
|
@@ -55,7 +62,7 @@ const prompts = function (inquirer) {
|
|
|
55
62
|
name: 'pageNames',
|
|
56
63
|
prefix: kleur.cyan('βΊ'),
|
|
57
64
|
message: ask('Page names', 'comma-separated for multi-page, blank for single-page'),
|
|
58
|
-
filter:
|
|
65
|
+
filter: trim
|
|
59
66
|
}
|
|
60
67
|
]);
|
|
61
68
|
};
|
package/.plop/utils/index.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Convert an arbitrary string to PascalCase. Drop-in replacement for the
|
|
3
|
+
* previous `_startCase(_camelCase(str)).replace(/ /g, '')` lodash chain so we
|
|
4
|
+
* don't pull in 70KB+ of lodash for two trivial string ops.
|
|
5
|
+
*
|
|
6
|
+
* Handles the input shapes plop prompts actually receive:
|
|
7
|
+
* "hello world" β "HelloWorld"
|
|
8
|
+
* "kebab-case-name" β "KebabCaseName"
|
|
9
|
+
* "snake_case_name" β "SnakeCaseName"
|
|
10
|
+
* "FOO_BAR" β "FooBar"
|
|
11
|
+
* "UPSDDO-1234 my-test" β "Upsddo1234MyTest"
|
|
12
|
+
* "alreadyCamel" β "AlreadyCamel"
|
|
13
|
+
* "MyComponent" β "MyComponent"
|
|
14
|
+
*/
|
|
4
15
|
exports.toPascalCase = str => {
|
|
5
|
-
|
|
16
|
+
if (!str) return '';
|
|
17
|
+
return String(str)
|
|
18
|
+
// insert space at lowerβUpper boundary: "fooBar" β "foo Bar"
|
|
19
|
+
.replace(/([a-z\d])([A-Z])/g, '$1 $2')
|
|
20
|
+
// insert space at UPPERβUpperlower boundary: "FOOBar" β "FOO Bar"
|
|
21
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
22
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
25
|
+
.join('');
|
|
6
26
|
};
|
|
7
27
|
|
|
8
28
|
/**
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ atb deploy
|
|
|
67
67
|
| `atb deploy` | Deploy activity to Adobe Target | `--dry-run` for testing, `--force` to override the 60s cooldown |
|
|
68
68
|
| `atb sync` | Sync `build.config.json` with the AT activity (pages, experiences, names) | `--scaffold` to auto-create missing variation folders |
|
|
69
69
|
| `atb doctor` | Diagnose and fix configuration issues | `--fix` to auto-fix |
|
|
70
|
-
| `atb install-extension` | Install the at-builder
|
|
70
|
+
| `atb install-extension` | Install the at-builder extension from the Marketplace (defaults to the VSCode `code` CLI) | `--editor agy` for Antigravity IDE; `--editor cursor`, `--editor codium`, or any VSCode-fork CLI on `PATH` |
|
|
71
71
|
|
|
72
72
|
### **Examples**
|
|
73
73
|
|
package/bin/constants/config.js
CHANGED
|
@@ -108,7 +108,7 @@ var getHelpInfo = function () { return __awaiter(void 0, void 0, void 0, functio
|
|
|
108
108
|
case 0: return [4 /*yield*/, (0, exports.getVersion)()];
|
|
109
109
|
case 1:
|
|
110
110
|
version = _a.sent();
|
|
111
|
-
return [2 /*return*/, "\n".concat(formatText("\uD83C\uDFAF at-builder", 'cyan', true), " ").concat(formatText("v".concat(version), 'gray'), "\n\n").concat(formatText("Adobe Target Activity Development CLI", 'white', true), "\n\nA streamlined command-line tool for creating, building, and deploying Adobe Target \nA/B testing activities with modern web technologies.\n\n").concat(formatText("USAGE", 'yellow', true), "\n ").concat(formatText("atb", 'cyan'), " ").concat(formatText("<command> [options]", 'gray'), "\n\n").concat(formatText("COMMANDS", 'yellow', true), "\n ").concat(formatText("init", 'cyan', true), " Initialize project with .env configuration and templates\n ").concat(formatText("new", 'cyan', true), " Create a new Adobe Target activity with variations\n ").concat(formatText("build", 'cyan', true), " Build activity for development\n ").concat(formatText("build --prod", 'cyan', true), " Build for production deployment\n ").concat(formatText("dev", 'cyan', true), " Start development server with file watching\n ").concat(formatText("dev --browser", 'cyan', true), " Start development server and open in browser\n ").concat(formatText("deploy", 'cyan', true), " Deploy activity to Adobe Target\n ").concat(formatText("deploy --dry-run", 'cyan', true), " Deploy in dry-run mode without actual deployment\n ").concat(formatText("deploy --force", 'cyan', true), " Override the 60s post-deploy cooldown lock\n ").concat(formatText("sync", 'cyan', true), " Sync build.config.json with the AT activity (pages, experiences, names)\n ").concat(formatText("sync --scaffold", 'cyan', true), " Sync and auto-create any missing variation folders with boilerplate\n ").concat(formatText("doctor", 'cyan', true), " Diagnose and fix project configuration issues\n ").concat(formatText("doctor --fix", 'cyan', true), " Automatically fix detected configuration issues\n ").concat(formatText("install-extension", 'cyan', true), " Install the
|
|
111
|
+
return [2 /*return*/, "\n".concat(formatText("\uD83C\uDFAF at-builder", 'cyan', true), " ").concat(formatText("v".concat(version), 'gray'), "\n\n").concat(formatText("Adobe Target Activity Development CLI", 'white', true), "\n\nA streamlined command-line tool for creating, building, and deploying Adobe Target \nA/B testing activities with modern web technologies.\n\n").concat(formatText("USAGE", 'yellow', true), "\n ").concat(formatText("atb", 'cyan'), " ").concat(formatText("<command> [options]", 'gray'), "\n\n").concat(formatText("COMMANDS", 'yellow', true), "\n ").concat(formatText("init", 'cyan', true), " Initialize project with .env configuration and templates\n ").concat(formatText("new", 'cyan', true), " Create a new Adobe Target activity with variations\n ").concat(formatText("build", 'cyan', true), " Build activity for development\n ").concat(formatText("build --prod", 'cyan', true), " Build for production deployment\n ").concat(formatText("dev", 'cyan', true), " Start development server with file watching\n ").concat(formatText("dev --browser", 'cyan', true), " Start development server and open in browser\n ").concat(formatText("deploy", 'cyan', true), " Deploy activity to Adobe Target\n ").concat(formatText("deploy --dry-run", 'cyan', true), " Deploy in dry-run mode without actual deployment\n ").concat(formatText("deploy --force", 'cyan', true), " Override the 60s post-deploy cooldown lock\n ").concat(formatText("sync", 'cyan', true), " Sync build.config.json with the AT activity (pages, experiences, names)\n ").concat(formatText("sync --scaffold", 'cyan', true), " Sync and auto-create any missing variation folders with boilerplate\n ").concat(formatText("doctor", 'cyan', true), " Diagnose and fix project configuration issues\n ").concat(formatText("doctor --fix", 'cyan', true), " Automatically fix detected configuration issues\n ").concat(formatText("install-extension", 'cyan', true), " Install the at-builder extension from the Marketplace (default: VSCode)\n ").concat(formatText("install-extension --editor agy", 'cyan', true), " Install into Antigravity IDE (also: cursor, codium, etc.)\n \n").concat(formatText("GLOBAL OPTIONS", 'yellow', true), "\n ").concat(formatText("-v, --verbose", 'green'), " Enable detailed logging\n ").concat(formatText("-V, --version", 'green'), " Display version information\n ").concat(formatText("-h, --help", 'green'), " Show help information\n\n").concat(formatText("EXAMPLES", 'yellow', true), "\n ").concat(formatText("# Initialize new project", 'gray'), "\n ").concat(formatText("atb init", 'white'), "\n \n ").concat(formatText("# Create new activity", 'gray'), "\n ").concat(formatText("atb new", 'white'), "\n \n ").concat(formatText("# Development build with hot reload", 'gray'), "\n ").concat(formatText("atb build", 'white'), "\n \n ").concat(formatText("# Production build for Adobe Target deployment", 'gray'), "\n ").concat(formatText("atb build --prod", 'white'), "\n \n ").concat(formatText("# Development server with browser", 'gray'), "\n ").concat(formatText("atb dev --browser", 'white'), "\n \n ").concat(formatText("# Deploy to Adobe Target", 'gray'), "\n ").concat(formatText("atb deploy", 'white'), "\n \n ").concat(formatText("# Deploy in dry-run mode", 'gray'), "\n ").concat(formatText("atb deploy --dry-run", 'white'), "\n\n ").concat(formatText("# Sync build.config.json from Adobe Target", 'gray'), "\n ").concat(formatText("atb sync", 'white'), "\n\n ").concat(formatText("# Sync and scaffold missing variation folders", 'gray'), "\n ").concat(formatText("atb sync --scaffold", 'white'), "\n\n ").concat(formatText("# Check project configuration", 'gray'), "\n ").concat(formatText("atb doctor", 'white'), "\n \n ").concat(formatText("# Auto-fix configuration issues", 'gray'), "\n ").concat(formatText("atb doctor --fix", 'white'), "\n\n").concat(formatText("WORKFLOW", 'yellow', true), "\n ").concat(formatText("1.", 'cyan'), " Run ").concat(formatText("atb init", 'white'), " to set up project configuration\n ").concat(formatText("2.", 'cyan'), " Run ").concat(formatText("atb new", 'white'), " to create activity templates \n ").concat(formatText("3.", 'cyan'), " Develop variations in ").concat(formatText("/Activities/{name}/Variation-*/", 'gray'), "\n ").concat(formatText("4.", 'cyan'), " Run ").concat(formatText("atb build", 'white'), " for development testing\n ").concat(formatText("5.", 'cyan'), " Run ").concat(formatText("atb build --prod", 'white'), " for Adobe Target deployment\n ").concat(formatText("6.", 'cyan'), " Run ").concat(formatText("atb deploy", 'white'), " to deploy to Adobe Target\n\n").concat(formatText("SUPPORT", 'yellow', true), "\n Repository: ").concat(formatText("https://github.com/upesenga/at-builder", 'blue'), "\n Issues: ").concat(formatText("https://github.com/upesenga/at-builder/issues", 'blue'), "\n License: ").concat(formatText("MIT", 'green'), "\n")];
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
114
|
}); };
|
|
@@ -192,27 +192,28 @@ var createAdobeConfig = function (basePath) {
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
/**
|
|
195
|
-
* Reads and returns environment variables from the specified .env file
|
|
196
|
-
*
|
|
197
|
-
*
|
|
195
|
+
* Reads and returns environment variables from the specified .env file.
|
|
196
|
+
*
|
|
197
|
+
* Throws if the file is missing or unreadable. Callers decide whether
|
|
198
|
+
* to surface the failure β printing here would spam every `atb` run from
|
|
199
|
+
* a directory that doesn't have a `.env` (e.g. `atb --version` from /tmp).
|
|
200
|
+
*
|
|
201
|
+
* @param basePath - The base path where the .env file is located
|
|
202
|
+
* @returns Object containing environment variables
|
|
198
203
|
*/
|
|
199
204
|
var getENV = function (basePath) { return __awaiter(void 0, void 0, void 0, function () {
|
|
200
|
-
var envPath, envContent,
|
|
205
|
+
var envPath, envContent, envVars;
|
|
201
206
|
return __generator(this, function (_a) {
|
|
202
207
|
switch (_a.label) {
|
|
203
208
|
case 0:
|
|
204
209
|
envPath = path_1.default.join(basePath, '.env');
|
|
205
|
-
_a.label = 1;
|
|
206
|
-
case 1:
|
|
207
|
-
_a.trys.push([1, 3, , 4]);
|
|
208
|
-
// Check if .env file exists
|
|
209
210
|
if (!fs_1.default.existsSync(envPath)) {
|
|
210
211
|
throw new Error('.env file not found');
|
|
211
212
|
}
|
|
212
213
|
return [4 /*yield*/, fs_1.default.promises.readFile(envPath, { encoding: 'utf8' })];
|
|
213
|
-
case
|
|
214
|
+
case 1:
|
|
214
215
|
envContent = _a.sent();
|
|
215
|
-
|
|
216
|
+
envVars = {};
|
|
216
217
|
envContent.split('\n').forEach(function (line) {
|
|
217
218
|
line = line.trim();
|
|
218
219
|
// Skip empty lines and comments
|
|
@@ -221,16 +222,11 @@ var getENV = function (basePath) { return __awaiter(void 0, void 0, void 0, func
|
|
|
221
222
|
if (key) {
|
|
222
223
|
var value = valueParts.join('=').trim();
|
|
223
224
|
// Remove quotes if present
|
|
224
|
-
|
|
225
|
+
envVars[key.trim()] = value.replace(/^["'](.*)["']$/, '$1');
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
});
|
|
228
|
-
return [2 /*return*/,
|
|
229
|
-
case 3:
|
|
230
|
-
error_2 = _a.sent();
|
|
231
|
-
console.error(cli_color_1.default.red("Error reading .env file: ".concat(error_2.message)));
|
|
232
|
-
throw error_2;
|
|
233
|
-
case 4: return [2 /*return*/];
|
|
229
|
+
return [2 /*return*/, envVars];
|
|
234
230
|
}
|
|
235
231
|
});
|
|
236
232
|
}); };
|
package/bin/index.js
CHANGED
|
@@ -230,8 +230,8 @@ var setupCommander = function () { return __awaiter(void 0, void 0, void 0, func
|
|
|
230
230
|
}); });
|
|
231
231
|
program
|
|
232
232
|
.command('install-extension')
|
|
233
|
-
.description('Install the
|
|
234
|
-
.option('--editor <bin>', 'Editor CLI to use (e.g. code, cursor, codium)', 'code')
|
|
233
|
+
.description('Install the at-builder VSCode extension from the Marketplace')
|
|
234
|
+
.option('--editor <bin>', 'Editor CLI to use (e.g. code, agy, cursor, codium)', 'code')
|
|
235
235
|
.action(function (options, command) { return __awaiter(void 0, void 0, void 0, function () {
|
|
236
236
|
var globalOpts;
|
|
237
237
|
return __generator(this, function (_a) {
|
|
@@ -382,50 +382,41 @@ var handleSync = function (scaffold, verbose) { return __awaiter(void 0, void 0,
|
|
|
382
382
|
/**
|
|
383
383
|
* Handles the install-extension command.
|
|
384
384
|
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*
|
|
385
|
+
* Installs the at-builder VSCode extension from the VS Code Marketplace
|
|
386
|
+
* using the editor's CLI. Defaults to `code`; users on Cursor/VSCodium
|
|
387
|
+
* can pass --editor.
|
|
388
|
+
*/
|
|
389
|
+
/**
|
|
390
|
+
* Per-editor install hints for when the CLI binary isn't on PATH. Each
|
|
391
|
+
* recognized editor gets a one-line, copy-pasteable suggestion. Anything
|
|
392
|
+
* else falls back to a generic hint.
|
|
391
393
|
*/
|
|
394
|
+
var EDITOR_INSTALL_HINTS = {
|
|
395
|
+
code: 'Open VSCode and run Command Palette β "Shell Command: Install \'code\' command in PATH".',
|
|
396
|
+
agy: 'Open Antigravity IDE and run Command Palette β "Shell Command: Install \'agy\' command in PATH".',
|
|
397
|
+
cursor: 'Open Cursor and run Command Palette β "Shell Command: Install \'cursor\' command in PATH".',
|
|
398
|
+
codium: 'Open VSCodium and run Command Palette β "Shell Command: Install \'codium\' command in PATH".',
|
|
399
|
+
};
|
|
400
|
+
var reportEditorNotFound = function (editor) {
|
|
401
|
+
console.error("\u274C \"".concat(editor, "\" CLI not found in PATH."));
|
|
402
|
+
var hint = EDITOR_INSTALL_HINTS[editor]
|
|
403
|
+
|| "Make sure the \"".concat(editor, "\" CLI is installed and on your PATH, or pass a different --editor.");
|
|
404
|
+
console.error("\uD83D\uDCA1 ".concat(hint));
|
|
405
|
+
};
|
|
392
406
|
var handleInstallExtension = function (editor, verbose) { return __awaiter(void 0, void 0, void 0, function () {
|
|
393
|
-
var
|
|
407
|
+
var extensionId, result;
|
|
394
408
|
return __generator(this, function (_a) {
|
|
409
|
+
extensionId = "UpendraSengar.at-builder";
|
|
395
410
|
if (verbose)
|
|
396
|
-
logger_1.default.info("verbose", "Installing
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
candidates = fs_1.default.readdirSync(installRoot)
|
|
400
|
-
.filter(function (f) { return /^at-builder-.+\.vsix$/.test(f); })
|
|
401
|
-
.sort()
|
|
402
|
-
.reverse(); // latest version first by lexicographic sort
|
|
403
|
-
}
|
|
404
|
-
catch (error) {
|
|
405
|
-
console.error("\u274C Failed to scan at-builder directory: ".concat(error.message));
|
|
406
|
-
process.exit(1);
|
|
407
|
-
}
|
|
408
|
-
if (candidates.length === 0) {
|
|
409
|
-
console.error("β No at-builder VSCode extension (.vsix) found bundled with this install.");
|
|
410
|
-
console.error("\uD83D\uDCA1 Expected at: ".concat(installRoot, "/at-builder-*.vsix"));
|
|
411
|
-
process.exit(1);
|
|
412
|
-
}
|
|
413
|
-
vsixPath = path_1.default.join(installRoot, candidates[0]);
|
|
414
|
-
console.log("\uD83D\uDCE6 Installing ".concat(candidates[0], " via \"").concat(editor, "\"..."));
|
|
415
|
-
result = (0, child_process_1.spawn)(editor, ["--install-extension", vsixPath], {
|
|
411
|
+
logger_1.default.info("verbose", "Installing ".concat(extensionId, " via ").concat(editor));
|
|
412
|
+
console.log("\uD83D\uDCE6 Installing ".concat(extensionId, " from the Marketplace via \"").concat(editor, "\"..."));
|
|
413
|
+
result = (0, child_process_1.spawn)(editor, ["--install-extension", extensionId], {
|
|
416
414
|
stdio: "inherit",
|
|
417
415
|
shell: true
|
|
418
416
|
});
|
|
419
417
|
result.on("error", function (err) {
|
|
420
|
-
// ENOENT here means the editor binary isn't on PATH.
|
|
421
418
|
if (err.code === "ENOENT") {
|
|
422
|
-
|
|
423
|
-
if (editor === "code") {
|
|
424
|
-
console.error("π‘ Open VSCode and run Command Palette β \"Shell Command: Install 'code' command in PATH\".");
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
console.error("\uD83D\uDCA1 Make sure the \"".concat(editor, "\" CLI is installed and on your PATH, or pass a different --editor."));
|
|
428
|
-
}
|
|
419
|
+
reportEditorNotFound(editor);
|
|
429
420
|
}
|
|
430
421
|
else {
|
|
431
422
|
console.error("\u274C Failed to launch \"".concat(editor, "\": ").concat(err.message));
|
|
@@ -440,13 +431,7 @@ var handleInstallExtension = function (editor, verbose) { return __awaiter(void
|
|
|
440
431
|
// 127 = shell's "command not found". With shell:true the spawn 'error'
|
|
441
432
|
// event never fires for missing CLIs, so we surface the same hint here.
|
|
442
433
|
if (code === 127) {
|
|
443
|
-
|
|
444
|
-
if (editor === "code") {
|
|
445
|
-
console.error("π‘ Open VSCode and run Command Palette β \"Shell Command: Install 'code' command in PATH\".");
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
console.error("\uD83D\uDCA1 Make sure the \"".concat(editor, "\" CLI is installed and on your PATH, or pass a different --editor."));
|
|
449
|
-
}
|
|
434
|
+
reportEditorNotFound(editor);
|
|
450
435
|
process.exit(1);
|
|
451
436
|
}
|
|
452
437
|
console.error("\u274C \"".concat(editor, " --install-extension\" exited with code ").concat(code, "."));
|
package/lib/at-deploy.js
CHANGED
|
@@ -47,7 +47,6 @@ dotenv.config({ path: path.join(PWD, '.env'), quiet: true });
|
|
|
47
47
|
|
|
48
48
|
const { execFileSync } = require('child_process');
|
|
49
49
|
const axios = require('axios');
|
|
50
|
-
const qs = require('querystring');
|
|
51
50
|
const fs = require('fs');
|
|
52
51
|
|
|
53
52
|
const { BASE_URL, IMS_TOKEN_URL, IMS_SCOPE } = require(path.join(PWD, 'adobe.config'));
|
|
@@ -207,12 +206,12 @@ function getBuildAssets(isMultiPage, allowedVariations) {
|
|
|
207
206
|
}
|
|
208
207
|
|
|
209
208
|
async function fetchAdobeToken() {
|
|
210
|
-
const data =
|
|
209
|
+
const data = new URLSearchParams({
|
|
211
210
|
grant_type: 'client_credentials',
|
|
212
211
|
client_id: process.env.ADOBE_CLIENT_ID,
|
|
213
212
|
client_secret: process.env.ADOBE_CLIENT_SECRET,
|
|
214
213
|
scope: IMS_SCOPE
|
|
215
|
-
});
|
|
214
|
+
}).toString();
|
|
216
215
|
try {
|
|
217
216
|
const res = await axios.post(IMS_TOKEN_URL, data, {
|
|
218
217
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
package/lib/at-sync.js
CHANGED
|
@@ -36,7 +36,6 @@
|
|
|
36
36
|
const path = require('path');
|
|
37
37
|
const fs = require('fs');
|
|
38
38
|
const axios = require('axios');
|
|
39
|
-
const qs = require('querystring');
|
|
40
39
|
const dotenv = require('dotenv');
|
|
41
40
|
|
|
42
41
|
const PWD = process.env.executionPath || process.cwd();
|
|
@@ -81,12 +80,12 @@ const CONFIG_PATHS = [
|
|
|
81
80
|
|
|
82
81
|
// βββ Auth βββ
|
|
83
82
|
async function fetchToken() {
|
|
84
|
-
const data =
|
|
83
|
+
const data = new URLSearchParams({
|
|
85
84
|
grant_type: 'client_credentials',
|
|
86
85
|
client_id: process.env.ADOBE_CLIENT_ID,
|
|
87
86
|
client_secret: process.env.ADOBE_CLIENT_SECRET,
|
|
88
87
|
scope: IMS_SCOPE
|
|
89
|
-
});
|
|
88
|
+
}).toString();
|
|
90
89
|
const res = await axios.post(IMS_TOKEN_URL, data, {
|
|
91
90
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
92
91
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "at-builder",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"main": "bin/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"atb": "bin/index.js"
|
|
@@ -22,18 +22,13 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@babel/core": "^7.26.9",
|
|
24
24
|
"@babel/eslint-parser": "^7.26.8",
|
|
25
|
-
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
26
|
-
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
27
25
|
"@babel/plugin-transform-runtime": "^7.18.9",
|
|
28
26
|
"@babel/preset-env": "^7.18.9",
|
|
29
|
-
"@babel/preset-react": "^7.18.6",
|
|
30
27
|
"@eslint/js": "^9.20.0",
|
|
31
28
|
"@types/node": "^22.13.2",
|
|
32
29
|
"async": "^3.2.3",
|
|
33
30
|
"axios": "^1.12.2",
|
|
34
31
|
"babel-loader": "^9.2.1",
|
|
35
|
-
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
|
36
|
-
"build": "^0.1.4",
|
|
37
32
|
"chokidar": "^4.0.3",
|
|
38
33
|
"cli-color": "^2.0.3",
|
|
39
34
|
"commander": "^13.1.0",
|
|
@@ -50,7 +45,6 @@
|
|
|
50
45
|
"postcss-loader": "^8.1.1",
|
|
51
46
|
"postcss-preset-env": "^10.1.4",
|
|
52
47
|
"puppeteer": "^24.2.0",
|
|
53
|
-
"querystring": "^0.2.1",
|
|
54
48
|
"readline": "^1.3.0",
|
|
55
49
|
"sass": "^1.53.0",
|
|
56
50
|
"sass-loader": "^16.0.4",
|
package/src/constants/config.ts
CHANGED
|
@@ -76,7 +76,8 @@ ${formatText("COMMANDS", 'yellow', true)}
|
|
|
76
76
|
${formatText("sync --scaffold", 'cyan', true)} Sync and auto-create any missing variation folders with boilerplate
|
|
77
77
|
${formatText("doctor", 'cyan', true)} Diagnose and fix project configuration issues
|
|
78
78
|
${formatText("doctor --fix", 'cyan', true)} Automatically fix detected configuration issues
|
|
79
|
-
${formatText("install-extension", 'cyan', true)} Install the at-builder
|
|
79
|
+
${formatText("install-extension", 'cyan', true)} Install the at-builder extension from the Marketplace (default: VSCode)
|
|
80
|
+
${formatText("install-extension --editor agy", 'cyan', true)} Install into Antigravity IDE (also: cursor, codium, etc.)
|
|
80
81
|
|
|
81
82
|
${formatText("GLOBAL OPTIONS", 'yellow', true)}
|
|
82
83
|
${formatText("-v, --verbose", 'green')} Enable detailed logging
|
|
@@ -278,39 +279,36 @@ module.exports = {
|
|
|
278
279
|
}
|
|
279
280
|
|
|
280
281
|
/**
|
|
281
|
-
* Reads and returns environment variables from the specified .env file
|
|
282
|
-
*
|
|
283
|
-
*
|
|
282
|
+
* Reads and returns environment variables from the specified .env file.
|
|
283
|
+
*
|
|
284
|
+
* Throws if the file is missing or unreadable. Callers decide whether
|
|
285
|
+
* to surface the failure β printing here would spam every `atb` run from
|
|
286
|
+
* a directory that doesn't have a `.env` (e.g. `atb --version` from /tmp).
|
|
287
|
+
*
|
|
288
|
+
* @param basePath - The base path where the .env file is located
|
|
289
|
+
* @returns Object containing environment variables
|
|
284
290
|
*/
|
|
285
291
|
export const getENV = async (basePath: string) => {
|
|
286
292
|
const envPath = path.join(basePath, '.env');
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
throw new Error('.env file not found');
|
|
291
|
-
}
|
|
293
|
+
if (!fs.existsSync(envPath)) {
|
|
294
|
+
throw new Error('.env file not found');
|
|
295
|
+
}
|
|
292
296
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (
|
|
302
|
-
const
|
|
303
|
-
if
|
|
304
|
-
|
|
305
|
-
// Remove quotes if present
|
|
306
|
-
envVars[key.trim()] = value.replace(/^["'](.*)["']$/, '$1');
|
|
307
|
-
}
|
|
297
|
+
const envContent = await fs.promises.readFile(envPath, { encoding: 'utf8' });
|
|
298
|
+
|
|
299
|
+
const envVars: { [key: string]: string } = {};
|
|
300
|
+
envContent.split('\n').forEach(line => {
|
|
301
|
+
line = line.trim();
|
|
302
|
+
// Skip empty lines and comments
|
|
303
|
+
if (line && !line.startsWith('#')) {
|
|
304
|
+
const [key, ...valueParts] = line.split('=');
|
|
305
|
+
if (key) {
|
|
306
|
+
const value = valueParts.join('=').trim();
|
|
307
|
+
// Remove quotes if present
|
|
308
|
+
envVars[key.trim()] = value.replace(/^["'](.*)["']$/, '$1');
|
|
308
309
|
}
|
|
309
|
-
}
|
|
310
|
+
}
|
|
311
|
+
});
|
|
310
312
|
|
|
311
|
-
|
|
312
|
-
} catch (error) {
|
|
313
|
-
console.error(clc.red(`Error reading .env file: ${error.message}`));
|
|
314
|
-
throw error;
|
|
315
|
-
}
|
|
313
|
+
return envVars;
|
|
316
314
|
};
|
package/src/index.ts
CHANGED
|
@@ -114,7 +114,7 @@ const setupCommander = async () => {
|
|
|
114
114
|
program
|
|
115
115
|
.command('install-extension')
|
|
116
116
|
.description('Install the at-builder VSCode extension from the Marketplace')
|
|
117
|
-
.option('--editor <bin>', 'Editor CLI to use (e.g. code, cursor, codium)', 'code')
|
|
117
|
+
.option('--editor <bin>', 'Editor CLI to use (e.g. code, agy, cursor, codium)', 'code')
|
|
118
118
|
.action(async (options, command) => {
|
|
119
119
|
const globalOpts = command.parent.opts();
|
|
120
120
|
await handleInstallExtension(options.editor, globalOpts.verbose);
|
|
@@ -250,6 +250,25 @@ const handleSync = async (scaffold: boolean, verbose: boolean): Promise<void> =>
|
|
|
250
250
|
* using the editor's CLI. Defaults to `code`; users on Cursor/VSCodium
|
|
251
251
|
* can pass --editor.
|
|
252
252
|
*/
|
|
253
|
+
/**
|
|
254
|
+
* Per-editor install hints for when the CLI binary isn't on PATH. Each
|
|
255
|
+
* recognized editor gets a one-line, copy-pasteable suggestion. Anything
|
|
256
|
+
* else falls back to a generic hint.
|
|
257
|
+
*/
|
|
258
|
+
const EDITOR_INSTALL_HINTS: Record<string, string> = {
|
|
259
|
+
code: 'Open VSCode and run Command Palette β "Shell Command: Install \'code\' command in PATH".',
|
|
260
|
+
agy: 'Open Antigravity IDE and run Command Palette β "Shell Command: Install \'agy\' command in PATH".',
|
|
261
|
+
cursor: 'Open Cursor and run Command Palette β "Shell Command: Install \'cursor\' command in PATH".',
|
|
262
|
+
codium: 'Open VSCodium and run Command Palette β "Shell Command: Install \'codium\' command in PATH".',
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const reportEditorNotFound = (editor: string): void => {
|
|
266
|
+
console.error(`β "${editor}" CLI not found in PATH.`);
|
|
267
|
+
const hint = EDITOR_INSTALL_HINTS[editor]
|
|
268
|
+
|| `Make sure the "${editor}" CLI is installed and on your PATH, or pass a different --editor.`;
|
|
269
|
+
console.error(`π‘ ${hint}`);
|
|
270
|
+
};
|
|
271
|
+
|
|
253
272
|
const handleInstallExtension = async (editor: string, verbose: boolean): Promise<void> => {
|
|
254
273
|
const extensionId = "UpendraSengar.at-builder";
|
|
255
274
|
|
|
@@ -264,12 +283,7 @@ const handleInstallExtension = async (editor: string, verbose: boolean): Promise
|
|
|
264
283
|
|
|
265
284
|
result.on("error", (err) => {
|
|
266
285
|
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
267
|
-
|
|
268
|
-
if (editor === "code") {
|
|
269
|
-
console.error("π‘ Open VSCode and run Command Palette β \"Shell Command: Install 'code' command in PATH\".");
|
|
270
|
-
} else {
|
|
271
|
-
console.error(`π‘ Make sure the "${editor}" CLI is installed and on your PATH, or pass a different --editor.`);
|
|
272
|
-
}
|
|
286
|
+
reportEditorNotFound(editor);
|
|
273
287
|
} else {
|
|
274
288
|
console.error(`β Failed to launch "${editor}": ${err.message}`);
|
|
275
289
|
}
|
|
@@ -281,13 +295,10 @@ const handleInstallExtension = async (editor: string, verbose: boolean): Promise
|
|
|
281
295
|
console.log("β
Extension installed. Reload your editor window to activate.");
|
|
282
296
|
return;
|
|
283
297
|
}
|
|
298
|
+
// 127 = shell's "command not found". With shell:true the spawn 'error'
|
|
299
|
+
// event never fires for missing CLIs, so we surface the same hint here.
|
|
284
300
|
if (code === 127) {
|
|
285
|
-
|
|
286
|
-
if (editor === "code") {
|
|
287
|
-
console.error("π‘ Open VSCode and run Command Palette β \"Shell Command: Install 'code' command in PATH\".");
|
|
288
|
-
} else {
|
|
289
|
-
console.error(`π‘ Make sure the "${editor}" CLI is installed and on your PATH, or pass a different --editor.`);
|
|
290
|
-
}
|
|
301
|
+
reportEditorNotFound(editor);
|
|
291
302
|
process.exit(1);
|
|
292
303
|
}
|
|
293
304
|
console.error(`β "${editor} --install-extension" exited with code ${code}.`);
|