at-builder 1.2.9 → 1.4.0

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/DEVELOPMENT.md ADDED
@@ -0,0 +1,164 @@
1
+ # Local Development
2
+
3
+ Notes-to-self on how to test `at-builder` against a real consumer project before publishing to npm. Not for end users — this is internal.
4
+
5
+ ---
6
+
7
+ ## TL;DR
8
+
9
+ ```bash
10
+ # one-time setup in this repo
11
+ yarn link
12
+ yarn build:atb:dev & # leave running; recompiles TS on save
13
+
14
+ # work against the bundled test/ sandbox (already gitignored, pre-populated)
15
+ cd test
16
+ atb doctor
17
+ atb new
18
+ atb dev --browser
19
+ # ... etc
20
+ ```
21
+
22
+ When done:
23
+
24
+ ```bash
25
+ # in at-builder
26
+ yarn unlink
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Two patterns
32
+
33
+ ### 1. `yarn link` — active iteration
34
+
35
+ Symlinks the global `atb` binary to this repo. Edits to source are picked up on the next invocation (after rebuild for TypeScript).
36
+
37
+ ```bash
38
+ # in at-builder
39
+ yarn link # or: npm link
40
+ ```
41
+
42
+ `atb` is now a global command pointing at this repo. Run it from any directory.
43
+
44
+ To remove the symlink later:
45
+
46
+ ```bash
47
+ yarn unlink # in at-builder
48
+ yarn unlink at-builder # in any project that also linked it (rarely needed)
49
+ ```
50
+
51
+ ### 2. `npm pack` — pre-publish verification
52
+
53
+ `yarn link` uses symlinks, which can paper over packaging issues — forgotten `.npmignore` exclusions, missing bundled assets (like `at-builder-*.vsix`), files declared in `package.json` but not actually present, etc. Before `npm publish`, do this to test the **actual artifact** npm will ship:
54
+
55
+ ```bash
56
+ # in at-builder
57
+ yarn build:atb # ensure bin/ is fresh
58
+ npm pack # produces at-builder-<version>.tgz
59
+
60
+ # in a clean throwaway directory
61
+ mkdir /tmp/atb-publish-test && cd /tmp/atb-publish-test
62
+ npm install -g /path/to/at-builder/at-builder-<version>.tgz
63
+
64
+ # verify the published surface
65
+ which atb
66
+ atb --version
67
+ atb install-extension --editor code # confirms the bundled .vsix actually shipped
68
+ atb init
69
+ # ... exercise other commands
70
+
71
+ # cleanup
72
+ npm uninstall -g at-builder
73
+ rm /path/to/at-builder/at-builder-<version>.tgz
74
+ ```
75
+
76
+ If anything's missing from the tarball, this catches it before users do.
77
+
78
+ ---
79
+
80
+ ## What needs rebuilding
81
+
82
+ The single thing that bites people most often:
83
+
84
+ | You edit | Rebuild needed? |
85
+ |---|---|
86
+ | `src/**/*.ts` (CLI surface) | **Yes** — `yarn build:atb` (one-shot) or `yarn build:atb:dev` (`tsc -w`) running in another terminal |
87
+ | `lib/at-deploy.js`, `lib/at-sync.js` | No — plain JS, picked up directly on next `atb` invocation |
88
+ | `puppeteer.js` | No |
89
+ | `webpack.config.js` | No |
90
+ | `.plop/generators/*`, `.plop/templates/*` | No |
91
+ | `babel.config.js`, `eslint.config.js`, `tsconfig.json` | No |
92
+
93
+ Easiest workflow: open a second terminal in this repo and leave `yarn build:atb:dev` running. Then any `src/` edit is reflected on the next `atb` invocation in your test project.
94
+
95
+ ---
96
+
97
+ ## The bundled `test/` sandbox
98
+
99
+ This repo ships a `test/` directory (gitignored) pre-populated with `.env`, `adobe.config.js`, `.gitignore`, and `package.json` — basically what `atb init` would create. Use it as a throwaway consumer project:
100
+
101
+ ```bash
102
+ cd test
103
+ atb doctor # exercises all checks
104
+ atb doctor --fix # exercises all auto-fixes (incl. watch-config migration)
105
+ atb new # exercise the prompts (AB/XT, page names)
106
+ atb sync # if you've set activityInfo.id
107
+ atb dev --browser # exercise the puppeteer fixes
108
+ atb deploy --dry-run # test deploy logic without PUTting to AT
109
+ atb install-extension # test the .vsix install flow
110
+ ```
111
+
112
+ If `test/` ever gets corrupted, just delete its contents and re-run `atb init` — it'll regenerate from scratch.
113
+
114
+ ---
115
+
116
+ ## Publishing checklist
117
+
118
+ Before `npm publish`:
119
+
120
+ 1. `yarn build:atb` — ensure `bin/` is fresh and committed.
121
+ 2. Bump `version` in `package.json`. Use semver:
122
+ - **patch** — bug fixes, doc changes
123
+ - **minor** — new commands, new flags, backwards-compatible features
124
+ - **major** — breaking schema changes (e.g. requiring fields, renaming commands)
125
+ 3. `npm pack` and run the verification block above.
126
+ 4. `git tag v<version>` + `git push --tags`.
127
+ 5. `npm publish`.
128
+
129
+ ---
130
+
131
+ ## Common gotchas
132
+
133
+ - **`atb` runs the wrong copy (link vs global)** — you have at-builder installed globally from npm AND linked locally. Run `which atb` and `atb --version`; if it doesn't match the local repo, `yarn unlink at-builder` (in linked consumer dirs) and `npm uninstall -g at-builder` to clear stale globals before re-linking.
134
+ - **`atb` resolves to a stale install in a *different* npm prefix** — distinct from the link-vs-global case above. It's easy to end up with at-builder installed at multiple locations (e.g. `/usr/local/lib/node_modules/at-builder` from a system npm AND `~/.nvm/versions/node/<v>/lib/node_modules/at-builder` from nvm). `npm install -g` only writes to the prefix the *currently-active* `npm` uses; a stale install in the *other* prefix can still come first on PATH. Diagnose:
135
+
136
+ ```bash
137
+ which -a atb # every atb on PATH
138
+ npm config get prefix # where the active npm installs
139
+ ls -la $(which atb) # see where the symlink points
140
+ ```
141
+
142
+ If `which -a` lists multiple entries, remove the stale one(s):
143
+
144
+ ```bash
145
+ # active prefix is nvm but a stale /usr/local install is shadowing it:
146
+ rm -f /usr/local/bin/atb
147
+ rm -rf /usr/local/lib/node_modules/at-builder
148
+
149
+ # or the reverse:
150
+ rm -f ~/.nvm/versions/node/<v>/bin/atb
151
+ rm -rf ~/.nvm/versions/node/<v>/lib/node_modules/at-builder
152
+ ```
153
+
154
+ Then reinstall once: `npm install -g /path/to/at-builder-<version>.tgz`.
155
+
156
+ - **`atb --version` shows the same number after re-packing** — `npm pack` honors whatever's in `package.json`; it doesn't bump for you. If you forgot to update the version before packing, the tarball reports the same number as the previously-published release and `atb --version` looks like nothing changed even though the code did. Always bump `package.json` first (see the publishing checklist for the semver rules), then re-pack. Verify before installing:
157
+
158
+ ```bash
159
+ tar xzOf at-builder-<version>.tgz package/package.json | grep '"version"'
160
+ ```
161
+
162
+ - **Edits to `src/` not reflected** — `bin/` is stale. Run `yarn build:atb` or check `yarn build:atb:dev` is actually running.
163
+ - **`npm install` exits 1** — historical issue, the `postinstall` script referenced a missing `bin/postinstall.js`. Already fixed (commit `d3fe05e`); if it resurfaces, drop the `postinstall` line from `package.json` again.
164
+ - **`.vsix` not in tarball** — verify with `npm pack --dry-run` before publishing. The `.vsix` lives at the repo root and is included by default (no `files` field, no `.npmignore` excluding it). If you ever add a `files` field, remember to whitelist `at-builder-*.vsix`.
package/README.md CHANGED
@@ -58,14 +58,16 @@ atb deploy
58
58
 
59
59
  ### **Core Commands**
60
60
 
61
- | Command | Description | Options |
62
- |---------|-------------|---------|
63
- | `atb init` | Initialize project with configuration files | |
64
- | `atb new` | Create new Adobe Target activity with variations | |
65
- | `atb build` | Build activity for development | `--prod` for production |
66
- | `atb dev` | Start development server with file watching | `--browser` to open browser |
67
- | `atb deploy` | Deploy activity to Adobe Target | `--dry-run` for testing |
68
- | `atb doctor` | Diagnose and fix configuration issues | `--fix` to auto-fix |
61
+ | Command | Description | Options |
62
+ | ----------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------- |
63
+ | `atb init` | Initialize project with configuration files | |
64
+ | `atb new` | Create new Adobe Target activity with variations | |
65
+ | `atb build` | Build activity for development | `--prod` for production |
66
+ | `atb dev` | Start development server with file watching | `--browser` to open browser |
67
+ | `atb deploy` | Deploy activity to Adobe Target | `--dry-run` for testing, `--force` to override the 60s cooldown |
68
+ | `atb sync` | Sync `build.config.json` with the AT activity (pages, experiences, names) | `--scaffold` to auto-create missing variation folders |
69
+ | `atb doctor` | Diagnose and fix configuration issues | `--fix` to auto-fix |
70
+ | `atb install-extension` | Install the at-builder VSCode extension from the Marketplace | `--editor cursor` (or `codium`, etc.) to use a non-VSCode editor CLI |
69
71
 
70
72
  ### **Examples**
71
73
 
@@ -88,6 +90,18 @@ atb dev --browser
88
90
  # Deploy to Adobe Target
89
91
  atb deploy
90
92
 
93
+ # Deploy in dry-run mode (no PUT to Adobe Target)
94
+ atb deploy --dry-run
95
+
96
+ # Force deploy and skip the 60s cooldown lock
97
+ atb deploy --force
98
+
99
+ # Sync build.config.json from Adobe Target
100
+ atb sync
101
+
102
+ # Sync and auto-create any missing variation folders
103
+ atb sync --scaffold
104
+
91
105
  # Check project configuration
92
106
  atb doctor
93
107
 
@@ -142,6 +156,7 @@ VARIATION="Variation-1"
142
156
  # Adobe Target Deployment
143
157
  ADOBE_CLIENT_ID="your-client-id"
144
158
  ADOBE_CLIENT_SECRET="your-client-secret"
159
+ ADOBE_TENANT="" # Optional. Your Adobe org slug (e.g."tst123"). Enables clickable AT UI links in deploy/sync output.
145
160
  ```
146
161
 
147
162
  ### **Adobe Target Configuration (adobe.config.js)**
Binary file
@@ -1,28 +1,75 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
2
38
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
40
  };
5
41
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getENV = exports.setupEnv = exports.getHelpInfo = exports.getVersion = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
9
- const cli_color_1 = __importDefault(require("cli-color"));
42
+ exports.getENV = exports.GITIGNORE_TEMPLATE = exports.setupEnv = exports.getHelpInfo = exports.getVersion = void 0;
43
+ var path_1 = __importDefault(require("path"));
44
+ var fs_1 = __importDefault(require("fs"));
45
+ var cli_color_1 = __importDefault(require("cli-color"));
10
46
  /**
11
47
  * Reads and returns the version from package.json
12
48
  * @returns {Promise<string>} The version of the package
13
49
  */
14
- const getVersion = async () => {
15
- const packageJSONPath = path_1.default.resolve(__dirname, "../../package.json");
16
- try {
17
- const content = await fs_1.default.promises.readFile(packageJSONPath, { encoding: "utf8" });
18
- const config = JSON.parse(content);
19
- return config.version;
20
- }
21
- catch (error) {
22
- console.error(cli_color_1.default.red("Error reading package.json or parsing JSON"));
23
- process.exit(1); // Exit the process if package.json is not found or malformed
24
- }
25
- };
50
+ var getVersion = function () { return __awaiter(void 0, void 0, void 0, function () {
51
+ var packageJSONPath, content, config, error_1;
52
+ return __generator(this, function (_a) {
53
+ switch (_a.label) {
54
+ case 0:
55
+ packageJSONPath = path_1.default.resolve(__dirname, "../../package.json");
56
+ _a.label = 1;
57
+ case 1:
58
+ _a.trys.push([1, 3, , 4]);
59
+ return [4 /*yield*/, fs_1.default.promises.readFile(packageJSONPath, { encoding: "utf8" })];
60
+ case 2:
61
+ content = _a.sent();
62
+ config = JSON.parse(content);
63
+ return [2 /*return*/, config.version];
64
+ case 3:
65
+ error_1 = _a.sent();
66
+ console.error(cli_color_1.default.red("Error reading package.json or parsing JSON"));
67
+ process.exit(1); // Exit the process if package.json is not found or malformed
68
+ return [3 /*break*/, 4];
69
+ case 4: return [2 /*return*/];
70
+ }
71
+ });
72
+ }); };
26
73
  exports.getVersion = getVersion;
27
74
  exports.getVersion = exports.getVersion;
28
75
  /**
@@ -33,10 +80,13 @@ exports.getVersion = exports.getVersion;
33
80
  * @param {boolean} underline Whether to underline the text
34
81
  * @returns {string} The formatted text
35
82
  */
36
- const formatText = (text, color = "white", bold = false, underline = false) => {
37
- let formattedText = text;
83
+ var formatText = function (text, color, bold, underline) {
84
+ if (color === void 0) { color = "white"; }
85
+ if (bold === void 0) { bold = false; }
86
+ if (underline === void 0) { underline = false; }
87
+ var formattedText = text;
38
88
  // Apply color
39
- const colorFn = cli_color_1.default[color];
89
+ var colorFn = cli_color_1.default[color];
40
90
  if (typeof colorFn === 'function') {
41
91
  formattedText = colorFn(text);
42
92
  }
@@ -51,116 +101,72 @@ const formatText = (text, color = "white", bold = false, underline = false) => {
51
101
  * Returns help information with commands and usage
52
102
  * @returns {Promise<string>} The help text
53
103
  */
54
- const getHelpInfo = async () => {
55
- const version = await (0, exports.getVersion)();
56
- return `
57
- ${formatText(`🎯 at-builder`, 'cyan', true)} ${formatText(`v${version}`, 'gray')}
58
-
59
- ${formatText("Adobe Target Activity Development CLI", 'white', true)}
60
-
61
- A streamlined command-line tool for creating, building, and deploying Adobe Target
62
- A/B testing activities with modern web technologies.
63
-
64
- ${formatText("USAGE", 'yellow', true)}
65
- ${formatText("atb", 'cyan')} ${formatText("<command> [options]", 'gray')}
66
-
67
- ${formatText("COMMANDS", 'yellow', true)}
68
- ${formatText("init", 'cyan', true)} Initialize project with .env configuration and templates
69
- ${formatText("new", 'cyan', true)} Create a new Adobe Target activity with variations
70
- ${formatText("build", 'cyan', true)} Build activity for development
71
- ${formatText("build --prod", 'cyan', true)} Build for production deployment
72
- ${formatText("dev", 'cyan', true)} Start development server with file watching
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
78
-
79
- ${formatText("GLOBAL OPTIONS", 'yellow', true)}
80
- ${formatText("-v, --verbose", 'green')} Enable detailed logging
81
- ${formatText("-V, --version", 'green')} Display version information
82
- ${formatText("-h, --help", 'green')} Show help information
83
-
84
- ${formatText("EXAMPLES", 'yellow', true)}
85
- ${formatText("# Initialize new project", 'gray')}
86
- ${formatText("atb init", 'white')}
87
-
88
- ${formatText("# Create new activity", 'gray')}
89
- ${formatText("atb new", 'white')}
90
-
91
- ${formatText("# Development build with hot reload", 'gray')}
92
- ${formatText("atb build", 'white')}
93
-
94
- ${formatText("# Production build for Adobe Target deployment", 'gray')}
95
- ${formatText("atb build --prod", 'white')}
96
-
97
- ${formatText("# Development server with browser", 'gray')}
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')}
111
-
112
- ${formatText("WORKFLOW", 'yellow', true)}
113
- ${formatText("1.", 'cyan')} Run ${formatText("atb init", 'white')} to set up project configuration
114
- ${formatText("2.", 'cyan')} Run ${formatText("atb new", 'white')} to create activity templates
115
- ${formatText("3.", 'cyan')} Develop variations in ${formatText("/Activities/{name}/Variation-*/", 'gray')}
116
- ${formatText("4.", 'cyan')} Run ${formatText("atb build", 'white')} for development testing
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
119
-
120
- ${formatText("SUPPORT", 'yellow', true)}
121
- Repository: ${formatText("https://github.com/upesenga/at-builder", 'blue')}
122
- Issues: ${formatText("https://github.com/upesenga/at-builder/issues", 'blue')}
123
- License: ${formatText("MIT", 'green')}
124
- `;
125
- };
104
+ var getHelpInfo = function () { return __awaiter(void 0, void 0, void 0, function () {
105
+ var version;
106
+ return __generator(this, function (_a) {
107
+ switch (_a.label) {
108
+ case 0: return [4 /*yield*/, (0, exports.getVersion)()];
109
+ case 1:
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 bundled at-builder VSCode extension (.vsix)\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
+ }
113
+ });
114
+ }); };
126
115
  exports.getHelpInfo = getHelpInfo;
127
- const setupEnv = async (basePath) => {
128
- // Path to the .env file
129
- const envPath = path_1.default.join(basePath, '.env');
130
- // Check if the .env file exists
131
- if (!fs_1.default.existsSync(envPath)) {
132
- // Define the content of the .env file
133
- const envContent = `
134
- ACTIVITIES_BASE_FOLDER="Activities"
135
- ACTIVITY_FOLDER_NAME=""
136
- PUPPETEER_LANDING_PAGE=""
137
- TARGET_URL=""
138
- LOGIN_URL=""
139
- VARIATION="Variation-1"
140
- NODE_ENV="development"
141
- VERBOSE=false
142
-
143
- # Adobe Target Deployment Configuration
144
- ADOBE_CLIENT_ID=""
145
- ADOBE_CLIENT_SECRET=""
146
- `;
147
- // Write the content to the .env file
148
- fs_1.default.writeFileSync(envPath, envContent.trim(), 'utf8');
149
- console.log('.env file created successfully!');
116
+ var setupEnv = function (basePath) { return __awaiter(void 0, void 0, void 0, function () {
117
+ var envPath, envContent;
118
+ return __generator(this, function (_a) {
119
+ envPath = path_1.default.join(basePath, '.env');
120
+ // Check if the .env file exists
121
+ if (!fs_1.default.existsSync(envPath)) {
122
+ envContent = "\nACTIVITIES_BASE_FOLDER=\"Activities\"\nACTIVITY_FOLDER_NAME=\"\"\nPUPPETEER_LANDING_PAGE=\"\"\nTARGET_URL=\"\"\nLOGIN_URL=\"\"\n\n# Dev-server selection (used by `atb dev --browser`).\n# Edit and save while puppeteer is running to hot-swap the previewed bundle.\n# PAGE is only meaningful for multi-page activities \u2014 leave empty otherwise.\nVARIATION=\"Variation-1\"\nPAGE=\"\"\n\nNODE_ENV=\"development\"\nVERBOSE=false\n\n# Adobe Target Deployment Configuration\n# ADOBE_TENANT is your AT tenant slug \u2014 find it in the AT URL after \"mc.adobe.io/\".\nADOBE_TENANT=\"\"\nADOBE_CLIENT_ID=\"\"\nADOBE_CLIENT_SECRET=\"\"\n ";
123
+ // Write the content to the .env file
124
+ fs_1.default.writeFileSync(envPath, envContent.trim(), 'utf8');
125
+ console.log('.env file created successfully!');
126
+ }
127
+ else {
128
+ console.log('.env file already exists!');
129
+ }
130
+ // watch-config.json is no longer scaffolded by `atb init` — VARIATION/PAGE
131
+ // now live in .env. Existing projects with a watch-config.json keep working
132
+ // (puppeteer.js prefers it with a deprecation warning); `atb doctor --fix`
133
+ // migrates the values into .env and deletes the legacy file.
134
+ createAdobeConfig(basePath);
135
+ createGitignore(basePath);
136
+ return [2 /*return*/];
137
+ });
138
+ }); };
139
+ exports.setupEnv = setupEnv;
140
+ /**
141
+ * Default .gitignore content for at-builder consumer projects.
142
+ *
143
+ * Shared between `atb init` (via setupEnv) and `atb doctor --fix` so the two
144
+ * paths stay in lockstep. Covers secrets, deploy-runtime artifacts, build
145
+ * output, and OS noise. Does NOT ignore the Activities folder — those are the
146
+ * user's source files and should be committed.
147
+ */
148
+ exports.GITIGNORE_TEMPLATE = "# Dependencies\nnode_modules/\n\n# Environment / secrets \u2014 never commit\n.env\n.env.local\n\n# Adobe Target deploy runtime (cooldown lock written by `atb deploy`)\n.deploy-lock\n\n# Build output (regenerated by `atb build`)\ndist/\n\n# OS noise\n.DS_Store\n\n# Editor / local-history\n.history/\n\n# Logs\n*.log\nnpm-debug.log*\n";
149
+ var createGitignore = function (basePath) {
150
+ var gitignorePath = path_1.default.join(basePath, '.gitignore');
151
+ if (!fs_1.default.existsSync(gitignorePath)) {
152
+ fs_1.default.writeFileSync(gitignorePath, exports.GITIGNORE_TEMPLATE, 'utf8');
153
+ console.log('.gitignore file created successfully!');
150
154
  }
151
155
  else {
152
- console.log('.env file already exists!');
156
+ console.log('.gitignore file already exists!');
153
157
  }
154
- createWatchConfig(basePath);
155
- createAdobeConfig(basePath);
156
158
  };
157
- exports.setupEnv = setupEnv;
158
- const createWatchConfig = (basePath) => {
159
+ var createWatchConfig = function (basePath) {
159
160
  // Path to the watch-config.json file
160
- const watchConfigPath = path_1.default.join(basePath, 'watch-config.json');
161
- // Default content for watch-config.json
162
- const watchConfigContent = {
163
- "VARIATION": "Variation-1"
161
+ var watchConfigPath = path_1.default.join(basePath, 'watch-config.json');
162
+ // Default content for watch-config.json.
163
+ // VARIATION : which variation/experience to preview in `atb dev --browser`
164
+ // PAGE : leave empty for single-page activities; set to the page
165
+ // subfolder name (e.g. "Global", "Cart") for multi-page.
166
+ // Editing this file mid-session hot-swaps the preview.
167
+ var watchConfigContent = {
168
+ "VARIATION": "Variation-1",
169
+ "PAGE": ""
164
170
  };
165
171
  // Check if the watch-config.json file already exists
166
172
  if (!fs_1.default.existsSync(watchConfigPath)) {
@@ -171,23 +177,11 @@ const createWatchConfig = (basePath) => {
171
177
  console.log('watch-config.json file already exists!');
172
178
  }
173
179
  };
174
- const createAdobeConfig = (basePath) => {
180
+ var createAdobeConfig = function (basePath) {
175
181
  // Path to the adobe.config.js file
176
- const adobeConfigPath = path_1.default.join(basePath, 'adobe.config.js');
182
+ var adobeConfigPath = path_1.default.join(basePath, 'adobe.config.js');
177
183
  // 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
- BASE_URL_NEW: 'https://mc.adobe.io/ups/target/',
187
- BASE_URL: 'https://mc.adobe.io/ups/target/activities/ab/',
188
- IMS_TOKEN_URL: 'https://ims-na1.adobelogin.com/ims/token/v3',
189
- IMS_SCOPE: 'openid,AdobeID,target_sdk,additional_info.projectedProductContext'
190
- };`;
184
+ var adobeConfigContent = "/**\n * Adobe Target API Configuration\n *\n * Used by at-sync.js and at-deploy.js. BASE_URL is the activities root \u2014\n * callers append `${activityType}/${activityId}` (e.g. ab/12345, xt/67890).\n *\n * ADOBE_TENANT comes from the consumer .env. Both at-sync and at-deploy load\n * dotenv before requiring this file, so process.env is populated by the time\n * BASE_URL is built.\n */\n\nconst TENANT = process.env.ADOBE_TENANT || 'YOUR_TENANT';\n\nmodule.exports = {\n BASE_URL: `https://mc.adobe.io/${TENANT}/target/activities/`,\n IMS_TOKEN_URL: 'https://ims-na1.adobelogin.com/ims/token/v3',\n IMS_SCOPE: 'openid,AdobeID,target_sdk,additional_info.projectedProductContext'\n};";
191
185
  // Check if the adobe.config.js file already exists
192
186
  if (!fs_1.default.existsSync(adobeConfigPath)) {
193
187
  fs_1.default.writeFileSync(adobeConfigPath, adobeConfigContent, 'utf8');
@@ -202,34 +196,42 @@ module.exports = {
202
196
  * @param {string} basePath - The base path where the .env file is located
203
197
  * @returns {Promise<Object>} Object containing environment variables
204
198
  */
205
- const getENV = async (basePath) => {
206
- const envPath = path_1.default.join(basePath, '.env');
207
- try {
208
- // Check if .env file exists
209
- if (!fs_1.default.existsSync(envPath)) {
210
- throw new Error('.env file not found');
211
- }
212
- // Read the .env file
213
- const envContent = await fs_1.default.promises.readFile(envPath, { encoding: 'utf8' });
214
- // Parse the .env file content
215
- const envVars = {};
216
- envContent.split('\n').forEach(line => {
217
- line = line.trim();
218
- // Skip empty lines and comments
219
- if (line && !line.startsWith('#')) {
220
- const [key, ...valueParts] = line.split('=');
221
- if (key) {
222
- const value = valueParts.join('=').trim();
223
- // Remove quotes if present
224
- envVars[key.trim()] = value.replace(/^["'](.*)["']$/, '$1');
199
+ var getENV = function (basePath) { return __awaiter(void 0, void 0, void 0, function () {
200
+ var envPath, envContent, envVars_1, error_2;
201
+ return __generator(this, function (_a) {
202
+ switch (_a.label) {
203
+ case 0:
204
+ 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
+ if (!fs_1.default.existsSync(envPath)) {
210
+ throw new Error('.env file not found');
225
211
  }
226
- }
227
- });
228
- return envVars;
229
- }
230
- catch (error) {
231
- console.error(cli_color_1.default.red(`Error reading .env file: ${error.message}`));
232
- throw error;
233
- }
234
- };
212
+ return [4 /*yield*/, fs_1.default.promises.readFile(envPath, { encoding: 'utf8' })];
213
+ case 2:
214
+ envContent = _a.sent();
215
+ envVars_1 = {};
216
+ envContent.split('\n').forEach(function (line) {
217
+ line = line.trim();
218
+ // Skip empty lines and comments
219
+ if (line && !line.startsWith('#')) {
220
+ var _a = line.split('='), key = _a[0], valueParts = _a.slice(1);
221
+ if (key) {
222
+ var value = valueParts.join('=').trim();
223
+ // Remove quotes if present
224
+ envVars_1[key.trim()] = value.replace(/^["'](.*)["']$/, '$1');
225
+ }
226
+ }
227
+ });
228
+ return [2 /*return*/, envVars_1];
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*/];
234
+ }
235
+ });
236
+ }); };
235
237
  exports.getENV = getENV;