at-builder 1.2.8 → 1.3.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 +53 -11
- package/.plop/constants/index.js +0 -7
- package/.plop/generators/actions.js +217 -126
- package/.plop/generators/prompts.js +50 -18
- package/.plop/utils/index.js +19 -5
- package/.vscode/settings.json +6 -0
- package/DEVELOPMENT.md +164 -0
- package/README.md +16 -1
- package/at-builder-0.0.2.vsix +0 -0
- package/bin/constants/config.js +169 -167
- package/bin/index.js +494 -182
- package/bin/services/doctor.js +752 -290
- package/bin/services/logger.js +40 -20
- package/lib/at-deploy.js +379 -145
- package/lib/at-sync.js +455 -0
- package/lib/eslint-flat-config-plugin.js +34 -33
- package/lib/install-checks.js +236 -0
- package/lib/postinstall.js +90 -0
- package/package/package.json +86 -0
- package/package.json +18 -11
- package/puppeteer.js +128 -32
- package/src/constants/config.ts +84 -9
- package/src/index.ts +131 -11
- package/src/services/doctor.ts +377 -39
- package/tsconfig.json +1 -1
- package/webpack.config.js +228 -39
- package/.plop/templates/build-template.hbs +0 -7
- package/.plop/templates/build.config.hbs +0 -7
- package/.plop/templates/observer.hbs +0 -18
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
|
@@ -64,8 +64,10 @@ atb deploy
|
|
|
64
64
|
| `atb new` | Create new Adobe Target activity with variations | |
|
|
65
65
|
| `atb build` | Build activity for development | `--prod` for production |
|
|
66
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 |
|
|
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 |
|
|
68
69
|
| `atb doctor` | Diagnose and fix configuration issues | `--fix` to auto-fix |
|
|
70
|
+
| `atb install-extension` | Install the bundled at-builder VSCode extension (.vsix) | `--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. "ups"). Enables clickable AT UI links in deploy/sync output.
|
|
145
160
|
```
|
|
146
161
|
|
|
147
162
|
### **Adobe Target Configuration (adobe.config.js)**
|
|
Binary file
|
package/bin/constants/config.js
CHANGED
|
@@ -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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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('.
|
|
156
|
+
console.log('.gitignore file already exists!');
|
|
153
157
|
}
|
|
154
|
-
createWatchConfig(basePath);
|
|
155
|
-
createAdobeConfig(basePath);
|
|
156
158
|
};
|
|
157
|
-
|
|
158
|
-
const createWatchConfig = (basePath) => {
|
|
159
|
+
var createWatchConfig = function (basePath) {
|
|
159
160
|
// Path to the watch-config.json file
|
|
160
|
-
|
|
161
|
-
// Default content for watch-config.json
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
180
|
+
var createAdobeConfig = function (basePath) {
|
|
175
181
|
// Path to the adobe.config.js file
|
|
176
|
-
|
|
182
|
+
var adobeConfigPath = path_1.default.join(basePath, 'adobe.config.js');
|
|
177
183
|
// Default content for adobe.config.js
|
|
178
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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;
|