@adsuploader/cli 0.1.2 → 0.1.4
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/SKILL.md +11 -0
- package/dist/cli.cjs +18 -6
- package/package.json +4 -2
package/SKILL.md
CHANGED
|
@@ -506,6 +506,15 @@ ads create spec.json
|
|
|
506
506
|
ads jobs JOB_ID --follow
|
|
507
507
|
```
|
|
508
508
|
|
|
509
|
+
`ads create` and `ads jobs --follow` watch for up to 30 minutes. On very large batches (hundreds of creatives), the command may exit before the job finishes with:
|
|
510
|
+
|
|
511
|
+
```
|
|
512
|
+
− Still running after 30 min — job continues on the server.
|
|
513
|
+
Resume with: ads jobs JOB_ID --follow
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
This is **not** a failure. The backend job keeps creating ads. Re-run the suggested command to resume watching. Exit code is `2` for this case (vs `0` for success, `1` for real errors) — shell scripts and agents should branch on the exit code to distinguish.
|
|
517
|
+
|
|
509
518
|
---
|
|
510
519
|
|
|
511
520
|
## Critical Gotchas
|
|
@@ -519,3 +528,5 @@ ads jobs JOB_ID --follow
|
|
|
519
528
|
7. **`textPresetId` and `texts` are mutually exclusive** — use one or the other
|
|
520
529
|
8. **Objective-specific CTAs** (`MESSAGE_PAGE`, `WHATSAPP_MESSAGE`, etc.) are inherited from the template — don't set them manually
|
|
521
530
|
9. **Do not use `--json`** — it's for shell scripts, not interactive use. The human-readable output has everything you need
|
|
531
|
+
10. **Never wrap CLI commands in polling loops** (`watch`, `while true; do ads adset X; sleep 5; done`, or equivalent). If you need to follow a job, use `ads jobs JOB_ID --follow`. If you need to verify ads landed after a create, run `ads adset <id>` **once** after the create returns — the job engine only marks complete when every ad is created on Facebook. Polling loops trigger rate limits (per-user-per-operation; list/read endpoints cap at 20/min) and return `429 Rate Limit Exceeded` with a `Retry-After` header.
|
|
532
|
+
11. **`ads create` exit code 2 means "still running," not "failed."** On very large batches the CLI stops watching after 30 minutes while the backend job continues. Resume with `ads jobs JOB_ID --follow`. Treat exit code 2 as "come back later," exit code 1 as a real error.
|
package/dist/cli.cjs
CHANGED
|
@@ -5182,7 +5182,8 @@ var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
|
5182
5182
|
// src/lib/poll.js
|
|
5183
5183
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
5184
5184
|
var POLL_INTERVAL = 500;
|
|
5185
|
-
var TIMEOUT_MS =
|
|
5185
|
+
var TIMEOUT_MS = 30 * 60 * 1e3;
|
|
5186
|
+
var TIMEOUT_MINUTES = TIMEOUT_MS / 6e4;
|
|
5186
5187
|
async function pollJob(client, jobId, opts = {}) {
|
|
5187
5188
|
const jsonMode = opts.json;
|
|
5188
5189
|
const tty = process.stdout.isTTY && !jsonMode;
|
|
@@ -5212,6 +5213,11 @@ async function pollJob(client, jobId, opts = {}) {
|
|
|
5212
5213
|
if (jsonMode) {
|
|
5213
5214
|
console.log(JSON.stringify(data));
|
|
5214
5215
|
if (data.complete) return data;
|
|
5216
|
+
if (Date.now() - startMs > TIMEOUT_MS) {
|
|
5217
|
+
console.log(JSON.stringify({ event: "still_running", jobId }));
|
|
5218
|
+
process.exitCode = 2;
|
|
5219
|
+
return { status: "still_running", jobId };
|
|
5220
|
+
}
|
|
5215
5221
|
await sleep(POLL_INTERVAL);
|
|
5216
5222
|
continue;
|
|
5217
5223
|
}
|
|
@@ -5255,10 +5261,16 @@ async function pollJob(client, jobId, opts = {}) {
|
|
|
5255
5261
|
return data;
|
|
5256
5262
|
}
|
|
5257
5263
|
if (Date.now() - startMs > TIMEOUT_MS) {
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5264
|
+
if (jsonMode) {
|
|
5265
|
+
console.log(JSON.stringify({ event: "still_running", jobId }));
|
|
5266
|
+
} else {
|
|
5267
|
+
console.log("");
|
|
5268
|
+
console.log(` ${import_picocolors10.default.yellow("\u2212")} ${import_picocolors10.default.yellow(`Still running after ${TIMEOUT_MINUTES} min \u2014 job continues on the server.`)}`);
|
|
5269
|
+
console.log(` Resume with: ${import_picocolors10.default.bold(`ads jobs ${jobId} --follow`)}`);
|
|
5270
|
+
console.log("");
|
|
5271
|
+
}
|
|
5272
|
+
process.exitCode = 2;
|
|
5273
|
+
return { status: "still_running", jobId };
|
|
5262
5274
|
}
|
|
5263
5275
|
await sleep(POLL_INTERVAL);
|
|
5264
5276
|
}
|
|
@@ -5917,7 +5929,7 @@ function statusLabel(status) {
|
|
|
5917
5929
|
}
|
|
5918
5930
|
|
|
5919
5931
|
// src/cli.js
|
|
5920
|
-
var VERSION = true ? "0.1.
|
|
5932
|
+
var VERSION = true ? "0.1.4" : "0.0.0";
|
|
5921
5933
|
var apiUrl = process.env.ADS_API_URL || getBaseUrl();
|
|
5922
5934
|
if (apiUrl && (apiUrl.includes("localhost") || apiUrl.includes("127.0.0.1"))) {
|
|
5923
5935
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adsuploader/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Create Facebook ads from the command line — bulk upload media, preview configurations, and launch ads at scale",
|
|
5
5
|
"author": "Ads Uploader <support@adsuploader.com> (https://adsuploader.com)",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "node build.cjs",
|
|
34
34
|
"dev": "node src/cli.js",
|
|
35
|
-
"link": "npm link"
|
|
35
|
+
"link": "npm link",
|
|
36
|
+
"prepublishOnly": "npm run build",
|
|
37
|
+
"version": "npm run build"
|
|
36
38
|
},
|
|
37
39
|
"dependencies": {
|
|
38
40
|
"commander": "^13.0.0",
|