@affonso/cli 0.1.3 → 0.1.5
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/dist/index.js +1216 -307
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -26,13 +26,880 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
// src/cli.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
28
|
|
|
29
|
-
//
|
|
30
|
-
var
|
|
29
|
+
// package.json
|
|
30
|
+
var package_default = {
|
|
31
|
+
name: "@affonso/cli",
|
|
32
|
+
version: "0.1.5",
|
|
33
|
+
description: "Command line interface for the Affonso affiliate marketing platform",
|
|
34
|
+
bin: {
|
|
35
|
+
affonso: "dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
files: [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
scripts: {
|
|
41
|
+
build: "tsup",
|
|
42
|
+
prepack: "npm run build -- --silent",
|
|
43
|
+
dev: "tsup --watch",
|
|
44
|
+
test: "vitest run",
|
|
45
|
+
"test:package": "npm run build && node scripts/smoke-package.mjs",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
lint: "biome check src/",
|
|
48
|
+
"lint:fix": "biome check --write src/",
|
|
49
|
+
typecheck: "tsc --noEmit"
|
|
50
|
+
},
|
|
51
|
+
engines: {
|
|
52
|
+
node: ">=18"
|
|
53
|
+
},
|
|
54
|
+
dependencies: {
|
|
55
|
+
"@affonso/sdk": "^0.2.0",
|
|
56
|
+
commander: "^12.0.0",
|
|
57
|
+
open: "^10.0.0"
|
|
58
|
+
},
|
|
59
|
+
devDependencies: {
|
|
60
|
+
"@biomejs/biome": "^1.9.0",
|
|
61
|
+
"@types/node": "^20.0.0",
|
|
62
|
+
tsup: "^8.0.0",
|
|
63
|
+
typescript: "^5.7.0",
|
|
64
|
+
vitest: "^2.0.0"
|
|
65
|
+
},
|
|
66
|
+
keywords: [
|
|
67
|
+
"affonso",
|
|
68
|
+
"affiliate",
|
|
69
|
+
"cli"
|
|
70
|
+
],
|
|
71
|
+
license: "MIT"
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// node_modules/@affonso/sdk/dist/index.mjs
|
|
75
|
+
var AffonsoError = class extends Error {
|
|
76
|
+
status;
|
|
77
|
+
code;
|
|
78
|
+
field;
|
|
79
|
+
details;
|
|
80
|
+
headers;
|
|
81
|
+
constructor(message, opts2) {
|
|
82
|
+
super(message);
|
|
83
|
+
this.name = "AffonsoError";
|
|
84
|
+
this.status = opts2?.status;
|
|
85
|
+
this.code = opts2?.code;
|
|
86
|
+
this.field = opts2?.field;
|
|
87
|
+
this.details = opts2?.details;
|
|
88
|
+
this.headers = opts2?.headers;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
var AuthenticationError = class extends AffonsoError {
|
|
92
|
+
constructor(message, opts2) {
|
|
93
|
+
super(message, { ...opts2, status: 401 });
|
|
94
|
+
this.name = "AuthenticationError";
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var PermissionError = class extends AffonsoError {
|
|
98
|
+
constructor(message, opts2) {
|
|
99
|
+
super(message, { ...opts2, status: 403 });
|
|
100
|
+
this.name = "PermissionError";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var NotFoundError = class extends AffonsoError {
|
|
104
|
+
constructor(message, opts2) {
|
|
105
|
+
super(message, { ...opts2, status: 404 });
|
|
106
|
+
this.name = "NotFoundError";
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var ValidationError = class extends AffonsoError {
|
|
110
|
+
details;
|
|
111
|
+
constructor(message, details, opts2) {
|
|
112
|
+
super(message, { ...opts2, status: 400, details });
|
|
113
|
+
this.name = "ValidationError";
|
|
114
|
+
this.details = details;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var DuplicateError = class extends AffonsoError {
|
|
118
|
+
constructor(message, opts2) {
|
|
119
|
+
super(message, { ...opts2, status: 409 });
|
|
120
|
+
this.name = "DuplicateError";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var RateLimitError = class extends AffonsoError {
|
|
124
|
+
retryAfter;
|
|
125
|
+
constructor(message, retryAfter, opts2) {
|
|
126
|
+
super(message, { ...opts2, status: 429 });
|
|
127
|
+
this.name = "RateLimitError";
|
|
128
|
+
this.retryAfter = retryAfter;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
var InternalError = class extends AffonsoError {
|
|
132
|
+
constructor(message, opts2) {
|
|
133
|
+
super(message, opts2);
|
|
134
|
+
this.name = "InternalError";
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var ConnectionError = class extends AffonsoError {
|
|
138
|
+
constructor(message) {
|
|
139
|
+
super(message, { status: void 0 });
|
|
140
|
+
this.name = "ConnectionError";
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
function errorFromResponse(status, body, headers) {
|
|
144
|
+
const err = body.error ?? {};
|
|
145
|
+
const message = err.message ?? `Request failed with status ${status}`;
|
|
146
|
+
const code = err.code;
|
|
147
|
+
const opts2 = { status, code, field: err.field, details: err.details, headers };
|
|
148
|
+
if (code === "VALIDATION_ERROR" || !code && status === 400) {
|
|
149
|
+
return new ValidationError(message, err.details ?? [], opts2);
|
|
150
|
+
}
|
|
151
|
+
if (code === "RATE_LIMIT_EXCEEDED" || !code && status === 429) {
|
|
152
|
+
const retry = headers.get("x-ratelimit-reset");
|
|
153
|
+
return new RateLimitError(message, retry ? Number(retry) : void 0, opts2);
|
|
154
|
+
}
|
|
155
|
+
if (code === "UNAUTHORIZED" || !code && status === 401) {
|
|
156
|
+
return new AuthenticationError(message, opts2);
|
|
157
|
+
}
|
|
158
|
+
if (code === "FORBIDDEN" || !code && status === 403) {
|
|
159
|
+
return new PermissionError(message, opts2);
|
|
160
|
+
}
|
|
161
|
+
if (code === "NOT_FOUND" || !code && status === 404) {
|
|
162
|
+
return new NotFoundError(message, opts2);
|
|
163
|
+
}
|
|
164
|
+
if (code === "DUPLICATE_ERROR" || !code && status === 409) {
|
|
165
|
+
return new DuplicateError(message, opts2);
|
|
166
|
+
}
|
|
167
|
+
if (status >= 500) return new InternalError(message, opts2);
|
|
168
|
+
return new AffonsoError(message, opts2);
|
|
169
|
+
}
|
|
170
|
+
var VERSION = true ? "0.2.0" : "0.1.0";
|
|
171
|
+
function buildQueryString(params) {
|
|
172
|
+
const parts = [];
|
|
173
|
+
for (const [key, value] of Object.entries(params)) {
|
|
174
|
+
if (value === void 0 || value === null) continue;
|
|
175
|
+
if (Array.isArray(value)) {
|
|
176
|
+
for (const v of value) {
|
|
177
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(v))}`);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
184
|
+
}
|
|
185
|
+
function isRetryable(status) {
|
|
186
|
+
return status === 429 || status >= 500;
|
|
187
|
+
}
|
|
188
|
+
function sleep(ms) {
|
|
189
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
190
|
+
}
|
|
191
|
+
function isNode() {
|
|
192
|
+
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
193
|
+
}
|
|
194
|
+
var HttpClient = class {
|
|
195
|
+
config;
|
|
196
|
+
constructor(config) {
|
|
197
|
+
this.config = config;
|
|
198
|
+
}
|
|
199
|
+
async request(opts2) {
|
|
200
|
+
const url = `${this.config.baseUrl}${opts2.path}${opts2.query ? buildQueryString(opts2.query) : ""}`;
|
|
201
|
+
const headers = {
|
|
202
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
203
|
+
"Content-Type": "application/json"
|
|
204
|
+
};
|
|
205
|
+
if (isNode()) {
|
|
206
|
+
headers["User-Agent"] = `affonso-sdk/${VERSION}`;
|
|
207
|
+
}
|
|
208
|
+
let lastError;
|
|
209
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
210
|
+
const controller = new AbortController();
|
|
211
|
+
const timeoutId = setTimeout(
|
|
212
|
+
() => controller.abort(new Error("Request timed out")),
|
|
213
|
+
this.config.timeout
|
|
214
|
+
);
|
|
215
|
+
try {
|
|
216
|
+
const response = await this.config.fetch(url, {
|
|
217
|
+
method: opts2.method,
|
|
218
|
+
headers,
|
|
219
|
+
body: opts2.body ? JSON.stringify(opts2.body) : void 0,
|
|
220
|
+
signal: controller.signal
|
|
221
|
+
});
|
|
222
|
+
clearTimeout(timeoutId);
|
|
223
|
+
if (response.status === 204) {
|
|
224
|
+
return void 0;
|
|
225
|
+
}
|
|
226
|
+
let body;
|
|
227
|
+
try {
|
|
228
|
+
body = await response.json();
|
|
229
|
+
} catch {
|
|
230
|
+
throw new AffonsoError(
|
|
231
|
+
`Expected JSON response but received unparseable body (status ${response.status})`,
|
|
232
|
+
{ status: response.status, headers: response.headers }
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
if (!response.ok || body.success === false) {
|
|
236
|
+
const error = errorFromResponse(response.status, body, response.headers);
|
|
237
|
+
if (isRetryable(response.status) && attempt < this.config.maxRetries) {
|
|
238
|
+
lastError = error;
|
|
239
|
+
const waitMs = this.getRetryDelay(attempt, response.headers);
|
|
240
|
+
await sleep(waitMs);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
return body;
|
|
246
|
+
} catch (err) {
|
|
247
|
+
clearTimeout(timeoutId);
|
|
248
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
249
|
+
const connErr = new ConnectionError("Request timed out");
|
|
250
|
+
if (attempt < this.config.maxRetries) {
|
|
251
|
+
lastError = connErr;
|
|
252
|
+
await sleep(this.getRetryDelay(attempt));
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
throw connErr;
|
|
256
|
+
}
|
|
257
|
+
if (err instanceof AffonsoError) {
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
if (err instanceof Error) {
|
|
261
|
+
const connErr = new ConnectionError(err.message);
|
|
262
|
+
if (attempt < this.config.maxRetries) {
|
|
263
|
+
lastError = connErr;
|
|
264
|
+
await sleep(this.getRetryDelay(attempt));
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
throw connErr;
|
|
268
|
+
}
|
|
269
|
+
throw err;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
throw lastError ?? new ConnectionError("Request failed after retries");
|
|
273
|
+
}
|
|
274
|
+
getRetryDelay(attempt, headers) {
|
|
275
|
+
if (headers) {
|
|
276
|
+
const reset = headers.get("x-ratelimit-reset");
|
|
277
|
+
if (reset) {
|
|
278
|
+
const resetMs = Number(reset) * 1e3 - Date.now();
|
|
279
|
+
if (resetMs > 0 && resetMs < 6e4) return resetMs;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return Math.min(1e3 * 2 ** attempt, 1e4);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
var OffsetPage = class _OffsetPage {
|
|
286
|
+
data;
|
|
287
|
+
pagination;
|
|
288
|
+
httpClient;
|
|
289
|
+
requestOpts;
|
|
290
|
+
constructor(data, pagination, httpClient, requestOpts) {
|
|
291
|
+
this.data = data;
|
|
292
|
+
this.pagination = pagination;
|
|
293
|
+
this.httpClient = httpClient;
|
|
294
|
+
this.requestOpts = requestOpts;
|
|
295
|
+
}
|
|
296
|
+
async getNextPage() {
|
|
297
|
+
if (!this.pagination.has_next_page) return null;
|
|
298
|
+
const nextOpts = {
|
|
299
|
+
...this.requestOpts,
|
|
300
|
+
query: {
|
|
301
|
+
...this.requestOpts.query,
|
|
302
|
+
page: this.pagination.page + 1
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const response = await this.httpClient.request(nextOpts);
|
|
306
|
+
return new _OffsetPage(response.data, response.pagination, this.httpClient, nextOpts);
|
|
307
|
+
}
|
|
308
|
+
async *autoPaginate(maxPages = 1e3) {
|
|
309
|
+
let page = this;
|
|
310
|
+
let pageCount = 0;
|
|
311
|
+
while (page && pageCount < maxPages) {
|
|
312
|
+
for (const item of page.data) {
|
|
313
|
+
yield item;
|
|
314
|
+
}
|
|
315
|
+
pageCount++;
|
|
316
|
+
page = await page.getNextPage();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
var CursorPage = class _CursorPage {
|
|
321
|
+
data;
|
|
322
|
+
hasMore;
|
|
323
|
+
httpClient;
|
|
324
|
+
requestOpts;
|
|
325
|
+
constructor(data, hasMore, httpClient, requestOpts) {
|
|
326
|
+
this.data = data;
|
|
327
|
+
this.hasMore = hasMore;
|
|
328
|
+
this.httpClient = httpClient;
|
|
329
|
+
this.requestOpts = requestOpts;
|
|
330
|
+
}
|
|
331
|
+
async getNextPage() {
|
|
332
|
+
if (!this.hasMore || this.data.length === 0) return null;
|
|
333
|
+
const lastId = this.data[this.data.length - 1].id;
|
|
334
|
+
const nextOpts = {
|
|
335
|
+
...this.requestOpts,
|
|
336
|
+
query: {
|
|
337
|
+
...this.requestOpts.query,
|
|
338
|
+
starting_after: lastId
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
const response = await this.httpClient.request(nextOpts);
|
|
342
|
+
return new _CursorPage(response.data, response.has_more, this.httpClient, nextOpts);
|
|
343
|
+
}
|
|
344
|
+
async *autoPaginate(maxPages = 1e3) {
|
|
345
|
+
let page = this;
|
|
346
|
+
let pageCount = 0;
|
|
347
|
+
while (page && pageCount < maxPages) {
|
|
348
|
+
for (const item of page.data) {
|
|
349
|
+
yield item;
|
|
350
|
+
}
|
|
351
|
+
pageCount++;
|
|
352
|
+
page = await page.getNextPage();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
var Affiliates = class {
|
|
357
|
+
httpClient;
|
|
358
|
+
constructor(httpClient) {
|
|
359
|
+
this.httpClient = httpClient;
|
|
360
|
+
}
|
|
361
|
+
async list(params) {
|
|
362
|
+
const query = params ? { ...params } : {};
|
|
363
|
+
const requestOpts = { method: "GET", path: "/affiliates", query };
|
|
364
|
+
const response = await this.httpClient.request(requestOpts);
|
|
365
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
366
|
+
}
|
|
367
|
+
async retrieve(id, params) {
|
|
368
|
+
const query = params ? { ...params } : void 0;
|
|
369
|
+
const response = await this.httpClient.request({
|
|
370
|
+
method: "GET",
|
|
371
|
+
path: `/affiliates/${encodeURIComponent(id)}`,
|
|
372
|
+
query
|
|
373
|
+
});
|
|
374
|
+
return response.data;
|
|
375
|
+
}
|
|
376
|
+
async create(params) {
|
|
377
|
+
const response = await this.httpClient.request({
|
|
378
|
+
method: "POST",
|
|
379
|
+
path: "/affiliates",
|
|
380
|
+
body: params
|
|
381
|
+
});
|
|
382
|
+
return response.data;
|
|
383
|
+
}
|
|
384
|
+
async update(id, params) {
|
|
385
|
+
const response = await this.httpClient.request({
|
|
386
|
+
method: "PUT",
|
|
387
|
+
path: `/affiliates/${encodeURIComponent(id)}`,
|
|
388
|
+
body: params
|
|
389
|
+
});
|
|
390
|
+
return response.data;
|
|
391
|
+
}
|
|
392
|
+
async del(id) {
|
|
393
|
+
return this.httpClient.request({
|
|
394
|
+
method: "DELETE",
|
|
395
|
+
path: `/affiliates/${encodeURIComponent(id)}`
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
var Clicks = class {
|
|
400
|
+
httpClient;
|
|
401
|
+
constructor(httpClient) {
|
|
402
|
+
this.httpClient = httpClient;
|
|
403
|
+
}
|
|
404
|
+
async create(params) {
|
|
405
|
+
const response = await this.httpClient.request({
|
|
406
|
+
method: "POST",
|
|
407
|
+
path: "/clicks",
|
|
408
|
+
body: params
|
|
409
|
+
});
|
|
410
|
+
return response.data;
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
var Commissions = class {
|
|
414
|
+
httpClient;
|
|
415
|
+
constructor(httpClient) {
|
|
416
|
+
this.httpClient = httpClient;
|
|
417
|
+
}
|
|
418
|
+
async list(params) {
|
|
419
|
+
const query = params ? { ...params } : {};
|
|
420
|
+
const requestOpts = { method: "GET", path: "/commissions", query };
|
|
421
|
+
const response = await this.httpClient.request(requestOpts);
|
|
422
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
423
|
+
}
|
|
424
|
+
async retrieve(id, params) {
|
|
425
|
+
const query = params ? { ...params } : void 0;
|
|
426
|
+
const response = await this.httpClient.request({
|
|
427
|
+
method: "GET",
|
|
428
|
+
path: `/commissions/${encodeURIComponent(id)}`,
|
|
429
|
+
query
|
|
430
|
+
});
|
|
431
|
+
return response.data;
|
|
432
|
+
}
|
|
433
|
+
async create(params) {
|
|
434
|
+
const response = await this.httpClient.request({
|
|
435
|
+
method: "POST",
|
|
436
|
+
path: "/commissions",
|
|
437
|
+
body: params
|
|
438
|
+
});
|
|
439
|
+
return response.data;
|
|
440
|
+
}
|
|
441
|
+
async update(id, params) {
|
|
442
|
+
const response = await this.httpClient.request({
|
|
443
|
+
method: "PUT",
|
|
444
|
+
path: `/commissions/${encodeURIComponent(id)}`,
|
|
445
|
+
body: params
|
|
446
|
+
});
|
|
447
|
+
return response.data;
|
|
448
|
+
}
|
|
449
|
+
async del(id) {
|
|
450
|
+
return this.httpClient.request({
|
|
451
|
+
method: "DELETE",
|
|
452
|
+
path: `/commissions/${encodeURIComponent(id)}`
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
var Coupons = class {
|
|
457
|
+
httpClient;
|
|
458
|
+
constructor(httpClient) {
|
|
459
|
+
this.httpClient = httpClient;
|
|
460
|
+
}
|
|
461
|
+
async list(params) {
|
|
462
|
+
const query = params ? { ...params } : {};
|
|
463
|
+
const requestOpts = { method: "GET", path: "/coupons", query };
|
|
464
|
+
const response = await this.httpClient.request(requestOpts);
|
|
465
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
466
|
+
}
|
|
467
|
+
async retrieve(id, params) {
|
|
468
|
+
const query = params ? { ...params } : void 0;
|
|
469
|
+
const response = await this.httpClient.request({
|
|
470
|
+
method: "GET",
|
|
471
|
+
path: `/coupons/${encodeURIComponent(id)}`,
|
|
472
|
+
query
|
|
473
|
+
});
|
|
474
|
+
return response.data;
|
|
475
|
+
}
|
|
476
|
+
async create(params) {
|
|
477
|
+
const response = await this.httpClient.request({
|
|
478
|
+
method: "POST",
|
|
479
|
+
path: "/coupons",
|
|
480
|
+
body: params
|
|
481
|
+
});
|
|
482
|
+
return response.data;
|
|
483
|
+
}
|
|
484
|
+
async del(id) {
|
|
485
|
+
return this.httpClient.request({
|
|
486
|
+
method: "DELETE",
|
|
487
|
+
path: `/coupons/${encodeURIComponent(id)}`
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
var EmbedTokens = class {
|
|
492
|
+
httpClient;
|
|
493
|
+
constructor(httpClient) {
|
|
494
|
+
this.httpClient = httpClient;
|
|
495
|
+
}
|
|
496
|
+
async create(params) {
|
|
497
|
+
const response = await this.httpClient.request({
|
|
498
|
+
method: "POST",
|
|
499
|
+
path: "/embed/token",
|
|
500
|
+
body: params
|
|
501
|
+
});
|
|
502
|
+
return response.data;
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
var Marketplace = class {
|
|
506
|
+
httpClient;
|
|
507
|
+
constructor(httpClient) {
|
|
508
|
+
this.httpClient = httpClient;
|
|
509
|
+
}
|
|
510
|
+
async list(params) {
|
|
511
|
+
const query = params ? { ...params } : {};
|
|
512
|
+
const requestOpts = { method: "GET", path: "/marketplace", query };
|
|
513
|
+
const response = await this.httpClient.request(requestOpts);
|
|
514
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
515
|
+
}
|
|
516
|
+
async retrieve(id) {
|
|
517
|
+
const response = await this.httpClient.request({
|
|
518
|
+
method: "GET",
|
|
519
|
+
path: `/marketplace/${encodeURIComponent(id)}`
|
|
520
|
+
});
|
|
521
|
+
return response.data;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
var Payouts = class {
|
|
525
|
+
httpClient;
|
|
526
|
+
constructor(httpClient) {
|
|
527
|
+
this.httpClient = httpClient;
|
|
528
|
+
}
|
|
529
|
+
async list(params) {
|
|
530
|
+
const query = params ? { ...params } : {};
|
|
531
|
+
const requestOpts = { method: "GET", path: "/payouts", query };
|
|
532
|
+
const response = await this.httpClient.request(requestOpts);
|
|
533
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
534
|
+
}
|
|
535
|
+
async retrieve(id) {
|
|
536
|
+
const response = await this.httpClient.request({
|
|
537
|
+
method: "GET",
|
|
538
|
+
path: `/payouts/${encodeURIComponent(id)}`
|
|
539
|
+
});
|
|
540
|
+
return response.data;
|
|
541
|
+
}
|
|
542
|
+
async update(id, params) {
|
|
543
|
+
const response = await this.httpClient.request({
|
|
544
|
+
method: "PUT",
|
|
545
|
+
path: `/payouts/${encodeURIComponent(id)}`,
|
|
546
|
+
body: params
|
|
547
|
+
});
|
|
548
|
+
return response.data;
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
var ProgramCreatives = class {
|
|
552
|
+
httpClient;
|
|
553
|
+
constructor(httpClient) {
|
|
554
|
+
this.httpClient = httpClient;
|
|
555
|
+
}
|
|
556
|
+
async list(params) {
|
|
557
|
+
const query = params ? { ...params } : {};
|
|
558
|
+
const requestOpts = { method: "GET", path: "/program/creatives", query };
|
|
559
|
+
const response = await this.httpClient.request(requestOpts);
|
|
560
|
+
return new OffsetPage(response.data, response.pagination, this.httpClient, requestOpts);
|
|
561
|
+
}
|
|
562
|
+
async retrieve(id) {
|
|
563
|
+
const response = await this.httpClient.request({
|
|
564
|
+
method: "GET",
|
|
565
|
+
path: `/program/creatives/${encodeURIComponent(id)}`
|
|
566
|
+
});
|
|
567
|
+
return response.data;
|
|
568
|
+
}
|
|
569
|
+
async create(params) {
|
|
570
|
+
const response = await this.httpClient.request({
|
|
571
|
+
method: "POST",
|
|
572
|
+
path: "/program/creatives",
|
|
573
|
+
body: params
|
|
574
|
+
});
|
|
575
|
+
return response.data;
|
|
576
|
+
}
|
|
577
|
+
async update(id, params) {
|
|
578
|
+
const response = await this.httpClient.request({
|
|
579
|
+
method: "PATCH",
|
|
580
|
+
path: `/program/creatives/${encodeURIComponent(id)}`,
|
|
581
|
+
body: params
|
|
582
|
+
});
|
|
583
|
+
return response.data;
|
|
584
|
+
}
|
|
585
|
+
async del(id) {
|
|
586
|
+
return this.httpClient.request({
|
|
587
|
+
method: "DELETE",
|
|
588
|
+
path: `/program/creatives/${encodeURIComponent(id)}`
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
var ProgramFraudRules = class {
|
|
593
|
+
httpClient;
|
|
594
|
+
constructor(httpClient) {
|
|
595
|
+
this.httpClient = httpClient;
|
|
596
|
+
}
|
|
597
|
+
async retrieve() {
|
|
598
|
+
const response = await this.httpClient.request({
|
|
599
|
+
method: "GET",
|
|
600
|
+
path: "/program/fraud-rules"
|
|
601
|
+
});
|
|
602
|
+
return response.data;
|
|
603
|
+
}
|
|
604
|
+
async update(params) {
|
|
605
|
+
const response = await this.httpClient.request({
|
|
606
|
+
method: "PATCH",
|
|
607
|
+
path: "/program/fraud-rules",
|
|
608
|
+
body: params
|
|
609
|
+
});
|
|
610
|
+
return response.data;
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
var ProgramGroups = class {
|
|
614
|
+
httpClient;
|
|
615
|
+
constructor(httpClient) {
|
|
616
|
+
this.httpClient = httpClient;
|
|
617
|
+
}
|
|
618
|
+
async list(params) {
|
|
619
|
+
const query = params ? { ...params } : void 0;
|
|
620
|
+
const response = await this.httpClient.request({
|
|
621
|
+
method: "GET",
|
|
622
|
+
path: "/program/groups",
|
|
623
|
+
query
|
|
624
|
+
});
|
|
625
|
+
return response.data;
|
|
626
|
+
}
|
|
627
|
+
async retrieve(id, params) {
|
|
628
|
+
const query = params ? { ...params } : void 0;
|
|
629
|
+
const response = await this.httpClient.request({
|
|
630
|
+
method: "GET",
|
|
631
|
+
path: `/program/groups/${encodeURIComponent(id)}`,
|
|
632
|
+
query
|
|
633
|
+
});
|
|
634
|
+
return response.data;
|
|
635
|
+
}
|
|
636
|
+
async create(params) {
|
|
637
|
+
const response = await this.httpClient.request({
|
|
638
|
+
method: "POST",
|
|
639
|
+
path: "/program/groups",
|
|
640
|
+
body: params
|
|
641
|
+
});
|
|
642
|
+
return response.data;
|
|
643
|
+
}
|
|
644
|
+
async update(id, params) {
|
|
645
|
+
const response = await this.httpClient.request({
|
|
646
|
+
method: "PATCH",
|
|
647
|
+
path: `/program/groups/${encodeURIComponent(id)}`,
|
|
648
|
+
body: params
|
|
649
|
+
});
|
|
650
|
+
return response.data;
|
|
651
|
+
}
|
|
652
|
+
async del(id) {
|
|
653
|
+
return this.httpClient.request({
|
|
654
|
+
method: "DELETE",
|
|
655
|
+
path: `/program/groups/${encodeURIComponent(id)}`
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
var ProgramNotifications = class {
|
|
660
|
+
httpClient;
|
|
661
|
+
constructor(httpClient) {
|
|
662
|
+
this.httpClient = httpClient;
|
|
663
|
+
}
|
|
664
|
+
async list() {
|
|
665
|
+
const response = await this.httpClient.request({
|
|
666
|
+
method: "GET",
|
|
667
|
+
path: "/program/notifications"
|
|
668
|
+
});
|
|
669
|
+
return response.data;
|
|
670
|
+
}
|
|
671
|
+
async update(emailTypeId, params) {
|
|
672
|
+
const response = await this.httpClient.request({
|
|
673
|
+
method: "PATCH",
|
|
674
|
+
path: `/program/notifications/${encodeURIComponent(emailTypeId)}`,
|
|
675
|
+
body: params
|
|
676
|
+
});
|
|
677
|
+
return response.data;
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
var ProgramPaymentTerms = class {
|
|
681
|
+
httpClient;
|
|
682
|
+
constructor(httpClient) {
|
|
683
|
+
this.httpClient = httpClient;
|
|
684
|
+
}
|
|
685
|
+
async retrieve() {
|
|
686
|
+
const response = await this.httpClient.request({
|
|
687
|
+
method: "GET",
|
|
688
|
+
path: "/program/payment-terms"
|
|
689
|
+
});
|
|
690
|
+
return response.data;
|
|
691
|
+
}
|
|
692
|
+
async update(params) {
|
|
693
|
+
const response = await this.httpClient.request({
|
|
694
|
+
method: "PATCH",
|
|
695
|
+
path: "/program/payment-terms",
|
|
696
|
+
body: params
|
|
697
|
+
});
|
|
698
|
+
return response.data;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
var ProgramPortal = class {
|
|
702
|
+
httpClient;
|
|
703
|
+
constructor(httpClient) {
|
|
704
|
+
this.httpClient = httpClient;
|
|
705
|
+
}
|
|
706
|
+
async retrieve() {
|
|
707
|
+
const response = await this.httpClient.request({
|
|
708
|
+
method: "GET",
|
|
709
|
+
path: "/program/portal"
|
|
710
|
+
});
|
|
711
|
+
return response.data;
|
|
712
|
+
}
|
|
713
|
+
async update(params) {
|
|
714
|
+
const response = await this.httpClient.request({
|
|
715
|
+
method: "PATCH",
|
|
716
|
+
path: "/program/portal",
|
|
717
|
+
body: params
|
|
718
|
+
});
|
|
719
|
+
return response.data;
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
var ProgramRestrictions = class {
|
|
723
|
+
httpClient;
|
|
724
|
+
constructor(httpClient) {
|
|
725
|
+
this.httpClient = httpClient;
|
|
726
|
+
}
|
|
727
|
+
async retrieve() {
|
|
728
|
+
const response = await this.httpClient.request({
|
|
729
|
+
method: "GET",
|
|
730
|
+
path: "/program/restrictions"
|
|
731
|
+
});
|
|
732
|
+
return response.data;
|
|
733
|
+
}
|
|
734
|
+
async update(params) {
|
|
735
|
+
const response = await this.httpClient.request({
|
|
736
|
+
method: "PATCH",
|
|
737
|
+
path: "/program/restrictions",
|
|
738
|
+
body: params
|
|
739
|
+
});
|
|
740
|
+
return response.data;
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
var ProgramSettingsResource = class {
|
|
744
|
+
httpClient;
|
|
745
|
+
constructor(httpClient) {
|
|
746
|
+
this.httpClient = httpClient;
|
|
747
|
+
}
|
|
748
|
+
async retrieve() {
|
|
749
|
+
const response = await this.httpClient.request({
|
|
750
|
+
method: "GET",
|
|
751
|
+
path: "/program"
|
|
752
|
+
});
|
|
753
|
+
return response.data;
|
|
754
|
+
}
|
|
755
|
+
async update(params) {
|
|
756
|
+
const response = await this.httpClient.request({
|
|
757
|
+
method: "PATCH",
|
|
758
|
+
path: "/program",
|
|
759
|
+
body: params
|
|
760
|
+
});
|
|
761
|
+
return response.data;
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
var ProgramTracking = class {
|
|
765
|
+
httpClient;
|
|
766
|
+
constructor(httpClient) {
|
|
767
|
+
this.httpClient = httpClient;
|
|
768
|
+
}
|
|
769
|
+
async retrieve() {
|
|
770
|
+
const response = await this.httpClient.request({
|
|
771
|
+
method: "GET",
|
|
772
|
+
path: "/program/tracking"
|
|
773
|
+
});
|
|
774
|
+
return response.data;
|
|
775
|
+
}
|
|
776
|
+
async update(params) {
|
|
777
|
+
const response = await this.httpClient.request({
|
|
778
|
+
method: "PATCH",
|
|
779
|
+
path: "/program/tracking",
|
|
780
|
+
body: params
|
|
781
|
+
});
|
|
782
|
+
return response.data;
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
var Program = class {
|
|
786
|
+
paymentTerms;
|
|
787
|
+
tracking;
|
|
788
|
+
restrictions;
|
|
789
|
+
groups;
|
|
790
|
+
creatives;
|
|
791
|
+
notifications;
|
|
792
|
+
portal;
|
|
793
|
+
fraudRules;
|
|
794
|
+
settings;
|
|
795
|
+
constructor(httpClient) {
|
|
796
|
+
this.settings = new ProgramSettingsResource(httpClient);
|
|
797
|
+
this.paymentTerms = new ProgramPaymentTerms(httpClient);
|
|
798
|
+
this.tracking = new ProgramTracking(httpClient);
|
|
799
|
+
this.restrictions = new ProgramRestrictions(httpClient);
|
|
800
|
+
this.groups = new ProgramGroups(httpClient);
|
|
801
|
+
this.creatives = new ProgramCreatives(httpClient);
|
|
802
|
+
this.notifications = new ProgramNotifications(httpClient);
|
|
803
|
+
this.portal = new ProgramPortal(httpClient);
|
|
804
|
+
this.fraudRules = new ProgramFraudRules(httpClient);
|
|
805
|
+
}
|
|
806
|
+
async retrieve() {
|
|
807
|
+
return this.settings.retrieve();
|
|
808
|
+
}
|
|
809
|
+
async update(params) {
|
|
810
|
+
return this.settings.update(params);
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
var Referrals = class {
|
|
814
|
+
httpClient;
|
|
815
|
+
constructor(httpClient) {
|
|
816
|
+
this.httpClient = httpClient;
|
|
817
|
+
}
|
|
818
|
+
async list(params) {
|
|
819
|
+
const query = params ? { ...params } : {};
|
|
820
|
+
const requestOpts = { method: "GET", path: "/referrals", query };
|
|
821
|
+
const response = await this.httpClient.request(requestOpts);
|
|
822
|
+
return new CursorPage(response.data, response.has_more, this.httpClient, requestOpts);
|
|
823
|
+
}
|
|
824
|
+
async retrieve(id, params) {
|
|
825
|
+
const query = params ? { ...params } : void 0;
|
|
826
|
+
const response = await this.httpClient.request({
|
|
827
|
+
method: "GET",
|
|
828
|
+
path: `/referrals/${encodeURIComponent(id)}`,
|
|
829
|
+
query
|
|
830
|
+
});
|
|
831
|
+
return response.data;
|
|
832
|
+
}
|
|
833
|
+
async create(params) {
|
|
834
|
+
const response = await this.httpClient.request({
|
|
835
|
+
method: "POST",
|
|
836
|
+
path: "/referrals",
|
|
837
|
+
body: params
|
|
838
|
+
});
|
|
839
|
+
return response.data;
|
|
840
|
+
}
|
|
841
|
+
async update(id, params) {
|
|
842
|
+
const response = await this.httpClient.request({
|
|
843
|
+
method: "PUT",
|
|
844
|
+
path: `/referrals/${encodeURIComponent(id)}`,
|
|
845
|
+
body: params
|
|
846
|
+
});
|
|
847
|
+
return response.data;
|
|
848
|
+
}
|
|
849
|
+
async del(id) {
|
|
850
|
+
return this.httpClient.request({
|
|
851
|
+
method: "DELETE",
|
|
852
|
+
path: `/referrals/${encodeURIComponent(id)}`
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
var DEFAULT_BASE_URL = "https://api.affonso.io/v1";
|
|
857
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
858
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
859
|
+
var Affonso = class {
|
|
860
|
+
affiliates;
|
|
861
|
+
referrals;
|
|
862
|
+
clicks;
|
|
863
|
+
commissions;
|
|
864
|
+
coupons;
|
|
865
|
+
payouts;
|
|
866
|
+
program;
|
|
867
|
+
embedTokens;
|
|
868
|
+
marketplace;
|
|
869
|
+
constructor(apiKey, config) {
|
|
870
|
+
if (!apiKey) {
|
|
871
|
+
throw new Error(
|
|
872
|
+
"An API key is required. Pass it as the first argument: new Affonso('sk_...')"
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
const httpConfig = {
|
|
876
|
+
apiKey,
|
|
877
|
+
baseUrl: config?.baseUrl ?? DEFAULT_BASE_URL,
|
|
878
|
+
timeout: config?.timeout ?? DEFAULT_TIMEOUT,
|
|
879
|
+
maxRetries: config?.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
880
|
+
fetch: config?.fetch ?? ((...args) => globalThis.fetch(...args))
|
|
881
|
+
};
|
|
882
|
+
const httpClient = new HttpClient(httpConfig);
|
|
883
|
+
this.affiliates = new Affiliates(httpClient);
|
|
884
|
+
this.referrals = new Referrals(httpClient);
|
|
885
|
+
this.clicks = new Clicks(httpClient);
|
|
886
|
+
this.commissions = new Commissions(httpClient);
|
|
887
|
+
this.coupons = new Coupons(httpClient);
|
|
888
|
+
this.payouts = new Payouts(httpClient);
|
|
889
|
+
this.program = new Program(httpClient);
|
|
890
|
+
this.embedTokens = new EmbedTokens(httpClient);
|
|
891
|
+
this.marketplace = new Marketplace(httpClient);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
// src/auth/oauth.ts
|
|
896
|
+
var import_node_crypto = __toESM(require("crypto"));
|
|
897
|
+
var import_node_http = __toESM(require("http"));
|
|
31
898
|
|
|
32
899
|
// src/auth/storage.ts
|
|
33
900
|
var import_node_fs = __toESM(require("fs"));
|
|
34
|
-
var import_node_path = __toESM(require("path"));
|
|
35
901
|
var import_node_os = __toESM(require("os"));
|
|
902
|
+
var import_node_path = __toESM(require("path"));
|
|
36
903
|
var CONFIG_DIR = import_node_path.default.join(import_node_os.default.homedir(), ".config", "affonso");
|
|
37
904
|
var AUTH_FILE = import_node_path.default.join(CONFIG_DIR, "auth.json");
|
|
38
905
|
var CONFIG_FILE = import_node_path.default.join(CONFIG_DIR, "config.json");
|
|
@@ -85,38 +952,7 @@ function saveConfig(config) {
|
|
|
85
952
|
});
|
|
86
953
|
}
|
|
87
954
|
|
|
88
|
-
// src/auth/resolve.ts
|
|
89
|
-
function resolveAuth(flagApiKey) {
|
|
90
|
-
if (flagApiKey) {
|
|
91
|
-
return { apiKey: flagApiKey, source: "flag" };
|
|
92
|
-
}
|
|
93
|
-
const envKey = process.env.AFFONSO_API_KEY;
|
|
94
|
-
if (envKey) {
|
|
95
|
-
return { apiKey: envKey, source: "env" };
|
|
96
|
-
}
|
|
97
|
-
const config = loadConfig();
|
|
98
|
-
if (config.api_key) {
|
|
99
|
-
return { apiKey: config.api_key, source: "config" };
|
|
100
|
-
}
|
|
101
|
-
const auth = loadAuth();
|
|
102
|
-
if (auth?.access_token) {
|
|
103
|
-
if (auth.expires_at && Date.now() > auth.expires_at) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
return { apiKey: auth.access_token, source: "oauth" };
|
|
107
|
-
}
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
function resolveBaseUrl(flagBaseUrl) {
|
|
111
|
-
if (flagBaseUrl) return flagBaseUrl;
|
|
112
|
-
const config = loadConfig();
|
|
113
|
-
if (config.base_url) return config.base_url;
|
|
114
|
-
return "https://api.affonso.io/v1";
|
|
115
|
-
}
|
|
116
|
-
|
|
117
955
|
// src/auth/oauth.ts
|
|
118
|
-
var import_node_crypto = __toESM(require("crypto"));
|
|
119
|
-
var import_node_http = __toESM(require("http"));
|
|
120
956
|
var CLIENT_ID = "d4e5f6a7-b8c9-4d0e-a1f2-b3c4d5e6f7a8";
|
|
121
957
|
var SCOPES = "read write";
|
|
122
958
|
var LOGIN_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -139,7 +975,7 @@ async function login(baseUrl) {
|
|
|
139
975
|
const { verifier, challenge } = generatePKCE();
|
|
140
976
|
return new Promise((resolve, reject) => {
|
|
141
977
|
const server = import_node_http.default.createServer(async (req, res) => {
|
|
142
|
-
const url = new URL(req.url ?? "/",
|
|
978
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
143
979
|
if (url.pathname !== "/callback") {
|
|
144
980
|
res.writeHead(404);
|
|
145
981
|
res.end("Not found");
|
|
@@ -254,17 +1090,46 @@ async function refreshToken(baseUrl, refreshTokenValue) {
|
|
|
254
1090
|
return false;
|
|
255
1091
|
}
|
|
256
1092
|
}
|
|
257
|
-
function successPage() {
|
|
258
|
-
return `<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
|
|
259
|
-
<h1>✓ Logged in to Affonso</h1>
|
|
260
|
-
<p>You can close this window and return to the terminal.</p>
|
|
261
|
-
</body></html>`;
|
|
262
|
-
}
|
|
263
|
-
function errorPage(message) {
|
|
264
|
-
return `<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
|
|
265
|
-
<h1>Authentication Error</h1>
|
|
266
|
-
<p>${escapeHtml(message)}</p>
|
|
267
|
-
</body></html>`;
|
|
1093
|
+
function successPage() {
|
|
1094
|
+
return `<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
|
|
1095
|
+
<h1>✓ Logged in to Affonso</h1>
|
|
1096
|
+
<p>You can close this window and return to the terminal.</p>
|
|
1097
|
+
</body></html>`;
|
|
1098
|
+
}
|
|
1099
|
+
function errorPage(message) {
|
|
1100
|
+
return `<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
|
|
1101
|
+
<h1>Authentication Error</h1>
|
|
1102
|
+
<p>${escapeHtml(message)}</p>
|
|
1103
|
+
</body></html>`;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// src/auth/resolve.ts
|
|
1107
|
+
function resolveAuth(flagApiKey) {
|
|
1108
|
+
if (flagApiKey) {
|
|
1109
|
+
return { apiKey: flagApiKey, source: "flag" };
|
|
1110
|
+
}
|
|
1111
|
+
const envKey = process.env.AFFONSO_API_KEY;
|
|
1112
|
+
if (envKey) {
|
|
1113
|
+
return { apiKey: envKey, source: "env" };
|
|
1114
|
+
}
|
|
1115
|
+
const config = loadConfig();
|
|
1116
|
+
if (config.api_key) {
|
|
1117
|
+
return { apiKey: config.api_key, source: "config" };
|
|
1118
|
+
}
|
|
1119
|
+
const auth = loadAuth();
|
|
1120
|
+
if (auth?.access_token) {
|
|
1121
|
+
if (auth.expires_at && Date.now() > auth.expires_at) {
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
return { apiKey: auth.access_token, source: "oauth" };
|
|
1125
|
+
}
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
function resolveBaseUrl(flagBaseUrl) {
|
|
1129
|
+
if (flagBaseUrl) return flagBaseUrl;
|
|
1130
|
+
const config = loadConfig();
|
|
1131
|
+
if (config.base_url) return config.base_url;
|
|
1132
|
+
return "https://api.affonso.io/v1";
|
|
268
1133
|
}
|
|
269
1134
|
|
|
270
1135
|
// src/lib/client.ts
|
|
@@ -278,7 +1143,9 @@ async function getClient(opts2) {
|
|
|
278
1143
|
if (refreshed) {
|
|
279
1144
|
auth = resolveAuth(opts2.apiKey);
|
|
280
1145
|
} else {
|
|
281
|
-
console.error(
|
|
1146
|
+
console.error(
|
|
1147
|
+
"Error: Session expired and token refresh failed. Run `affonso login` to re-authenticate."
|
|
1148
|
+
);
|
|
282
1149
|
process.exit(1);
|
|
283
1150
|
}
|
|
284
1151
|
}
|
|
@@ -287,13 +1154,12 @@ async function getClient(opts2) {
|
|
|
287
1154
|
console.error("Error: Authentication required. Run `affonso login` or set AFFONSO_API_KEY.");
|
|
288
1155
|
process.exit(1);
|
|
289
1156
|
}
|
|
290
|
-
return new
|
|
1157
|
+
return new Affonso(auth.apiKey, { baseUrl });
|
|
291
1158
|
}
|
|
292
1159
|
|
|
293
1160
|
// src/lib/errors.ts
|
|
294
|
-
var import_sdk2 = require("@affonso/sdk");
|
|
295
1161
|
function handleError(err, json) {
|
|
296
|
-
if (err instanceof
|
|
1162
|
+
if (err instanceof AffonsoError) {
|
|
297
1163
|
if (json) {
|
|
298
1164
|
console.error(
|
|
299
1165
|
JSON.stringify(
|
|
@@ -334,7 +1200,13 @@ function handleError(err, json) {
|
|
|
334
1200
|
}
|
|
335
1201
|
if (err instanceof Error) {
|
|
336
1202
|
if (json) {
|
|
337
|
-
console.error(
|
|
1203
|
+
console.error(
|
|
1204
|
+
JSON.stringify(
|
|
1205
|
+
{ success: false, error: { code: "CLI_ERROR", message: err.message } },
|
|
1206
|
+
null,
|
|
1207
|
+
2
|
|
1208
|
+
)
|
|
1209
|
+
);
|
|
338
1210
|
} else {
|
|
339
1211
|
console.error(`Error: ${err.message}`);
|
|
340
1212
|
}
|
|
@@ -388,9 +1260,11 @@ function formatTable(data, columns) {
|
|
|
388
1260
|
return truncated.padEnd(widths[col]);
|
|
389
1261
|
}).join(" ")
|
|
390
1262
|
);
|
|
391
|
-
|
|
392
|
-
|
|
1263
|
+
const tableWidth = cols.reduce(
|
|
1264
|
+
(total, col) => total + widths[col],
|
|
1265
|
+
Math.max(0, cols.length - 1) * 2
|
|
393
1266
|
);
|
|
1267
|
+
return [header, dim("\u2500".repeat(tableWidth)), ...rows].join("\n");
|
|
394
1268
|
}
|
|
395
1269
|
function formatValue(val) {
|
|
396
1270
|
if (val === null || val === void 0) return "\u2014";
|
|
@@ -422,10 +1296,8 @@ function output(result, opts2, columns) {
|
|
|
422
1296
|
console.log(formatTable(result.data, columns));
|
|
423
1297
|
if (result.pagination) {
|
|
424
1298
|
const p = result.pagination;
|
|
425
|
-
console.log(
|
|
426
|
-
|
|
427
|
-
Page ${p.page}/${p.total_pages} (${p.total} total)`
|
|
428
|
-
);
|
|
1299
|
+
console.log(`
|
|
1300
|
+
Page ${p.page}/${p.total_pages} (${p.total} total)`);
|
|
429
1301
|
}
|
|
430
1302
|
return;
|
|
431
1303
|
}
|
|
@@ -469,7 +1341,14 @@ function registerAffiliateCommands(program2) {
|
|
|
469
1341
|
dateFrom: o.dateFrom,
|
|
470
1342
|
dateTo: o.dateTo
|
|
471
1343
|
});
|
|
472
|
-
output(result, o, [
|
|
1344
|
+
output(result, o, [
|
|
1345
|
+
"id",
|
|
1346
|
+
"name",
|
|
1347
|
+
"email",
|
|
1348
|
+
"partnership_status",
|
|
1349
|
+
"tracking_id",
|
|
1350
|
+
"created_at"
|
|
1351
|
+
]);
|
|
473
1352
|
} catch (err) {
|
|
474
1353
|
handleError(err, o.json);
|
|
475
1354
|
}
|
|
@@ -536,88 +1415,6 @@ function registerAffiliateCommands(program2) {
|
|
|
536
1415
|
});
|
|
537
1416
|
}
|
|
538
1417
|
|
|
539
|
-
// src/commands/referrals.ts
|
|
540
|
-
function registerReferralCommands(program2) {
|
|
541
|
-
const referrals = program2.command("referrals").description("Manage referrals");
|
|
542
|
-
referrals.command("list").description("List referrals").option("--limit <n>", "Items per page", "50").option("--starting-after <id>", "Cursor: fetch items after this ID").option("--ending-before <id>", "Cursor: fetch items before this ID").option("--affiliate-id <id>", "Filter by affiliate ID").option("--status <status>", "Filter by status").option("--order <dir>", "Order (asc, desc)").option("--expand <fields>", "Expand fields").option("--created-gte <date>", "Created after date").option("--created-lte <date>", "Created before date").action(async function() {
|
|
543
|
-
const o = opts(this);
|
|
544
|
-
try {
|
|
545
|
-
const client = await getClient(o);
|
|
546
|
-
const result = await client.referrals.list({
|
|
547
|
-
limit: Number(o.limit),
|
|
548
|
-
starting_after: o.startingAfter,
|
|
549
|
-
ending_before: o.endingBefore,
|
|
550
|
-
affiliate_id: o.affiliateId,
|
|
551
|
-
status: o.status,
|
|
552
|
-
order: o.order,
|
|
553
|
-
expand: o.expand,
|
|
554
|
-
created_gte: o.createdGte,
|
|
555
|
-
created_lte: o.createdLte
|
|
556
|
-
});
|
|
557
|
-
output(result, o, ["id", "affiliate_id", "email", "status", "created_at"]);
|
|
558
|
-
} catch (err) {
|
|
559
|
-
handleError(err, o.json);
|
|
560
|
-
}
|
|
561
|
-
});
|
|
562
|
-
referrals.command("get <id>").description("Get a referral by ID").option("--expand <fields>", "Expand fields").option("--include <fields>", "Include fields").action(async function(id) {
|
|
563
|
-
const o = opts(this);
|
|
564
|
-
try {
|
|
565
|
-
const client = await getClient(o);
|
|
566
|
-
const result = await client.referrals.retrieve(id, {
|
|
567
|
-
expand: o.expand,
|
|
568
|
-
include: o.include
|
|
569
|
-
});
|
|
570
|
-
output(result, o);
|
|
571
|
-
} catch (err) {
|
|
572
|
-
handleError(err, o.json);
|
|
573
|
-
}
|
|
574
|
-
});
|
|
575
|
-
referrals.command("create").description("Create a referral").requiredOption("--email <email>", "Referral email").requiredOption("--affiliate-id <id>", "Affiliate ID").option("--subscription-id <id>", "Subscription ID").option("--customer-id <id>", "Customer ID").option("--click-id <id>", "Click ID").option("--status <status>", "Initial status").option("--name <name>", "Referral name").action(async function() {
|
|
576
|
-
const o = opts(this);
|
|
577
|
-
try {
|
|
578
|
-
const client = await getClient(o);
|
|
579
|
-
const result = await client.referrals.create({
|
|
580
|
-
email: o.email,
|
|
581
|
-
affiliate_id: o.affiliateId,
|
|
582
|
-
subscription_id: o.subscriptionId,
|
|
583
|
-
customer_id: o.customerId,
|
|
584
|
-
click_id: o.clickId,
|
|
585
|
-
status: o.status,
|
|
586
|
-
name: o.name
|
|
587
|
-
});
|
|
588
|
-
output(result, o);
|
|
589
|
-
} catch (err) {
|
|
590
|
-
handleError(err, o.json);
|
|
591
|
-
}
|
|
592
|
-
});
|
|
593
|
-
referrals.command("update <id>").description("Update a referral").option("--email <email>", "Referral email").option("--status <status>", "Status").option("--subscription-id <id>", "Subscription ID").option("--customer-id <id>", "Customer ID").option("--name <name>", "Referral name").action(async function(id) {
|
|
594
|
-
const o = opts(this);
|
|
595
|
-
try {
|
|
596
|
-
const client = await getClient(o);
|
|
597
|
-
const params = {};
|
|
598
|
-
if (o.email !== void 0) params.email = o.email;
|
|
599
|
-
if (o.status !== void 0) params.status = o.status;
|
|
600
|
-
if (o.subscriptionId !== void 0) params.subscription_id = o.subscriptionId;
|
|
601
|
-
if (o.customerId !== void 0) params.customer_id = o.customerId;
|
|
602
|
-
if (o.name !== void 0) params.name = o.name;
|
|
603
|
-
const result = await client.referrals.update(id, params);
|
|
604
|
-
output(result, o);
|
|
605
|
-
} catch (err) {
|
|
606
|
-
handleError(err, o.json);
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
referrals.command("delete <id>").description("Delete a referral").action(async function(id) {
|
|
610
|
-
const o = opts(this);
|
|
611
|
-
try {
|
|
612
|
-
const client = await getClient(o);
|
|
613
|
-
const result = await client.referrals.del(id);
|
|
614
|
-
outputSuccess(result.message ?? "Referral deleted.", o);
|
|
615
|
-
} catch (err) {
|
|
616
|
-
handleError(err, o.json);
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
|
|
621
1418
|
// src/commands/clicks.ts
|
|
622
1419
|
function registerClickCommands(program2) {
|
|
623
1420
|
const clicks = program2.command("clicks").description("Track click events");
|
|
@@ -732,86 +1529,253 @@ function registerCommissionCommands(program2) {
|
|
|
732
1529
|
handleError(err, o.json);
|
|
733
1530
|
}
|
|
734
1531
|
});
|
|
735
|
-
commissions.command("delete <id>").description("Delete a commission").action(async function(id) {
|
|
1532
|
+
commissions.command("delete <id>").description("Delete a commission").action(async function(id) {
|
|
1533
|
+
const o = opts(this);
|
|
1534
|
+
try {
|
|
1535
|
+
const client = await getClient(o);
|
|
1536
|
+
const result = await client.commissions.del(id);
|
|
1537
|
+
outputSuccess(result.message ?? "Commission deleted.", o);
|
|
1538
|
+
} catch (err) {
|
|
1539
|
+
handleError(err, o.json);
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// src/commands/config.ts
|
|
1545
|
+
var VALID_KEYS = ["api-key", "base-url"];
|
|
1546
|
+
var KEY_MAP = {
|
|
1547
|
+
"api-key": "api_key",
|
|
1548
|
+
"base-url": "base_url"
|
|
1549
|
+
};
|
|
1550
|
+
function registerConfigCommands(program2) {
|
|
1551
|
+
const config = program2.command("config").description("Manage CLI configuration");
|
|
1552
|
+
config.command("get <key>").description("Get a config value (api-key, base-url)").action(async function(key) {
|
|
1553
|
+
const o = opts(this);
|
|
1554
|
+
try {
|
|
1555
|
+
if (!VALID_KEYS.includes(key)) {
|
|
1556
|
+
console.error(`Unknown config key: ${key}. Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
1557
|
+
process.exit(1);
|
|
1558
|
+
}
|
|
1559
|
+
const stored = loadConfig();
|
|
1560
|
+
const mappedKey = KEY_MAP[key];
|
|
1561
|
+
const value = stored[mappedKey];
|
|
1562
|
+
if (value) {
|
|
1563
|
+
if (key === "api-key") {
|
|
1564
|
+
const v = value;
|
|
1565
|
+
console.log(`${v.slice(0, 10)}...${v.slice(-4)}`);
|
|
1566
|
+
} else {
|
|
1567
|
+
console.log(value);
|
|
1568
|
+
}
|
|
1569
|
+
} else {
|
|
1570
|
+
console.log(`${key} is not set.`);
|
|
1571
|
+
}
|
|
1572
|
+
} catch (err) {
|
|
1573
|
+
handleError(err, o.json);
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
config.command("set <key> <value>").description("Set a config value (api-key, base-url)").action(async function(key, value) {
|
|
1577
|
+
const o = opts(this);
|
|
1578
|
+
try {
|
|
1579
|
+
if (!VALID_KEYS.includes(key)) {
|
|
1580
|
+
console.error(`Unknown config key: ${key}. Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
1581
|
+
process.exit(1);
|
|
1582
|
+
}
|
|
1583
|
+
const mappedKey = KEY_MAP[key];
|
|
1584
|
+
saveConfig({ [mappedKey]: value });
|
|
1585
|
+
console.log(`${key} saved.`);
|
|
1586
|
+
} catch (err) {
|
|
1587
|
+
handleError(err, o.json);
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
// src/commands/coupons.ts
|
|
1593
|
+
function registerCouponCommands(program2) {
|
|
1594
|
+
const coupons = program2.command("coupons").description("Manage coupons");
|
|
1595
|
+
coupons.command("list").description("List coupons").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option("--affiliate-id <id>", "Filter by affiliate ID").option("--program-id <id>", "Filter by program ID").option("--search <query>", "Search by code").option("--expand <fields>", "Expand fields").option("--sort <field:dir>", "Sort").action(async function() {
|
|
1596
|
+
const o = opts(this);
|
|
1597
|
+
try {
|
|
1598
|
+
const client = await getClient(o);
|
|
1599
|
+
const result = await client.coupons.list({
|
|
1600
|
+
limit: Number(o.limit),
|
|
1601
|
+
page: Number(o.page),
|
|
1602
|
+
affiliate_id: o.affiliateId,
|
|
1603
|
+
program_id: o.programId,
|
|
1604
|
+
search: o.search,
|
|
1605
|
+
expand: o.expand,
|
|
1606
|
+
sort: o.sort
|
|
1607
|
+
});
|
|
1608
|
+
output(result, o, [
|
|
1609
|
+
"id",
|
|
1610
|
+
"affiliate_id",
|
|
1611
|
+
"code",
|
|
1612
|
+
"discount_type",
|
|
1613
|
+
"discount_value",
|
|
1614
|
+
"duration",
|
|
1615
|
+
"created_at"
|
|
1616
|
+
]);
|
|
1617
|
+
} catch (err) {
|
|
1618
|
+
handleError(err, o.json);
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
coupons.command("get <id>").description("Get a coupon by ID").option("--expand <fields>", "Expand fields").action(async function(id) {
|
|
1622
|
+
const o = opts(this);
|
|
1623
|
+
try {
|
|
1624
|
+
const client = await getClient(o);
|
|
1625
|
+
const result = await client.coupons.retrieve(id, {
|
|
1626
|
+
expand: o.expand
|
|
1627
|
+
});
|
|
1628
|
+
output(result, o);
|
|
1629
|
+
} catch (err) {
|
|
1630
|
+
handleError(err, o.json);
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
coupons.command("create").description("Create a coupon").requiredOption("--affiliate-id <id>", "Affiliate ID").requiredOption("--code <code>", "Coupon code").requiredOption("--discount-type <type>", "Discount type (percentage, fixed)").requiredOption("--discount-value <n>", "Discount value").requiredOption("--duration <dur>", "Duration (forever, once, repeating)").option("--duration-in-months <n>", "Duration in months (for repeating)").option("--currency <code>", "Currency code").option("--product-ids <ids>", "Product IDs (comma-separated)").action(async function() {
|
|
1634
|
+
const o = opts(this);
|
|
1635
|
+
try {
|
|
1636
|
+
const client = await getClient(o);
|
|
1637
|
+
const result = await client.coupons.create({
|
|
1638
|
+
affiliate_id: o.affiliateId,
|
|
1639
|
+
code: o.code,
|
|
1640
|
+
discount_type: o.discountType,
|
|
1641
|
+
discount_value: Number(o.discountValue),
|
|
1642
|
+
duration: o.duration,
|
|
1643
|
+
duration_in_months: o.durationInMonths ? Number(o.durationInMonths) : void 0,
|
|
1644
|
+
currency: o.currency,
|
|
1645
|
+
product_ids: o.productIds?.split(",")
|
|
1646
|
+
});
|
|
1647
|
+
output(result, o);
|
|
1648
|
+
} catch (err) {
|
|
1649
|
+
handleError(err, o.json);
|
|
1650
|
+
}
|
|
1651
|
+
});
|
|
1652
|
+
coupons.command("delete <id>").description("Delete a coupon").action(async function(id) {
|
|
1653
|
+
const o = opts(this);
|
|
1654
|
+
try {
|
|
1655
|
+
const client = await getClient(o);
|
|
1656
|
+
const result = await client.coupons.del(id);
|
|
1657
|
+
outputSuccess(result.message ?? "Coupon deleted.", o);
|
|
1658
|
+
} catch (err) {
|
|
1659
|
+
handleError(err, o.json);
|
|
1660
|
+
}
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
// src/commands/embed-tokens.ts
|
|
1665
|
+
function registerEmbedTokenCommands(program2) {
|
|
1666
|
+
const embedTokens = program2.command("embed-tokens").description("Generate embed tokens");
|
|
1667
|
+
embedTokens.command("create").description("Create an embed token").option("--affiliate-id <id>", "Affiliate ID").option("--external-user-id <id>", "External user ID").option("--email <email>", "Partner email").option("--name <name>", "Partner name").action(async function() {
|
|
1668
|
+
const o = opts(this);
|
|
1669
|
+
try {
|
|
1670
|
+
const client = await getClient(o);
|
|
1671
|
+
const result = await client.embedTokens.create({
|
|
1672
|
+
affiliate_id: o.affiliateId,
|
|
1673
|
+
external_user_id: o.externalUserId,
|
|
1674
|
+
email: o.email,
|
|
1675
|
+
name: o.name
|
|
1676
|
+
});
|
|
1677
|
+
output(result, o);
|
|
1678
|
+
} catch (err) {
|
|
1679
|
+
handleError(err, o.json);
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
// src/commands/login.ts
|
|
1685
|
+
function registerLoginCommand(program2) {
|
|
1686
|
+
program2.command("login").description("Log in via browser (OAuth 2.1)").action(async function() {
|
|
736
1687
|
const o = opts(this);
|
|
737
1688
|
try {
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
1689
|
+
const existing = resolveAuth();
|
|
1690
|
+
if (existing?.source === "oauth") {
|
|
1691
|
+
console.log("Already logged in. Run `affonso logout` first to switch accounts.");
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
const baseUrl = resolveBaseUrl(o.baseUrl);
|
|
1695
|
+
await login(baseUrl);
|
|
1696
|
+
console.log("Successfully logged in!");
|
|
741
1697
|
} catch (err) {
|
|
742
1698
|
handleError(err, o.json);
|
|
743
1699
|
}
|
|
744
1700
|
});
|
|
745
1701
|
}
|
|
746
1702
|
|
|
747
|
-
// src/commands/
|
|
748
|
-
function
|
|
749
|
-
|
|
750
|
-
coupons.command("list").description("List coupons").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option("--affiliate-id <id>", "Filter by affiliate ID").option("--program-id <id>", "Filter by program ID").option("--search <query>", "Search by code").option("--expand <fields>", "Expand fields").option("--sort <field:dir>", "Sort").action(async function() {
|
|
1703
|
+
// src/commands/logout.ts
|
|
1704
|
+
function registerLogoutCommand(program2) {
|
|
1705
|
+
program2.command("logout").description("Log out and remove stored credentials").action(async function() {
|
|
751
1706
|
const o = opts(this);
|
|
752
1707
|
try {
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
1708
|
+
const auth = loadAuth();
|
|
1709
|
+
if (auth?.access_token) {
|
|
1710
|
+
const baseUrl = resolveBaseUrl(o.baseUrl);
|
|
1711
|
+
const issuer = baseUrl.replace(/\/v1\/?$/, "");
|
|
1712
|
+
try {
|
|
1713
|
+
await fetch(`${issuer}/oauth/revoke`, {
|
|
1714
|
+
method: "POST",
|
|
1715
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1716
|
+
body: new URLSearchParams({
|
|
1717
|
+
token: auth.access_token,
|
|
1718
|
+
client_id: CLIENT_ID
|
|
1719
|
+
})
|
|
1720
|
+
});
|
|
1721
|
+
} catch {
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
clearAuth();
|
|
1725
|
+
console.log("Logged out.");
|
|
764
1726
|
} catch (err) {
|
|
765
1727
|
handleError(err, o.json);
|
|
766
1728
|
}
|
|
767
1729
|
});
|
|
768
|
-
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
// src/commands/marketplace.ts
|
|
1733
|
+
function registerMarketplaceCommands(program2) {
|
|
1734
|
+
const marketplace = program2.command("marketplace").description("Browse the affiliate marketplace (public, no auth required)");
|
|
1735
|
+
marketplace.command("list").description("List marketplace programs").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option("--category <cat>", "Filter by category").option("--search <query>", "Search programs").option("--sort <field:dir>", "Sort").action(async function() {
|
|
769
1736
|
const o = opts(this);
|
|
770
1737
|
try {
|
|
771
|
-
const
|
|
772
|
-
const
|
|
773
|
-
|
|
1738
|
+
const baseUrl = resolveBaseUrl(o.baseUrl);
|
|
1739
|
+
const client = new Affonso("public", { baseUrl });
|
|
1740
|
+
const result = await client.marketplace.list({
|
|
1741
|
+
limit: Number(o.limit),
|
|
1742
|
+
page: Number(o.page),
|
|
1743
|
+
category: o.category,
|
|
1744
|
+
search: o.search,
|
|
1745
|
+
sort: o.sort
|
|
774
1746
|
});
|
|
775
|
-
output(result, o
|
|
1747
|
+
output(result, o, [
|
|
1748
|
+
"id",
|
|
1749
|
+
"name",
|
|
1750
|
+
"category",
|
|
1751
|
+
"commission_type",
|
|
1752
|
+
"commission_rate",
|
|
1753
|
+
"cookie_lifetime"
|
|
1754
|
+
]);
|
|
776
1755
|
} catch (err) {
|
|
777
1756
|
handleError(err, o.json);
|
|
778
1757
|
}
|
|
779
1758
|
});
|
|
780
|
-
|
|
1759
|
+
marketplace.command("get <id>").description("Get a marketplace program by ID").action(async function(id) {
|
|
781
1760
|
const o = opts(this);
|
|
782
1761
|
try {
|
|
783
|
-
const
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
code: o.code,
|
|
787
|
-
discount_type: o.discountType,
|
|
788
|
-
discount_value: Number(o.discountValue),
|
|
789
|
-
duration: o.duration,
|
|
790
|
-
duration_in_months: o.durationInMonths ? Number(o.durationInMonths) : void 0,
|
|
791
|
-
currency: o.currency,
|
|
792
|
-
product_ids: o.productIds?.split(",")
|
|
793
|
-
});
|
|
1762
|
+
const baseUrl = resolveBaseUrl(o.baseUrl);
|
|
1763
|
+
const client = new Affonso("public", { baseUrl });
|
|
1764
|
+
const result = await client.marketplace.retrieve(id);
|
|
794
1765
|
output(result, o);
|
|
795
1766
|
} catch (err) {
|
|
796
1767
|
handleError(err, o.json);
|
|
797
1768
|
}
|
|
798
1769
|
});
|
|
799
|
-
coupons.command("delete <id>").description("Delete a coupon").action(async function(id) {
|
|
800
|
-
const o = opts(this);
|
|
801
|
-
try {
|
|
802
|
-
const client = await getClient(o);
|
|
803
|
-
const result = await client.coupons.del(id);
|
|
804
|
-
outputSuccess(result.message ?? "Coupon deleted.", o);
|
|
805
|
-
} catch (err) {
|
|
806
|
-
handleError(err, o.json);
|
|
807
|
-
}
|
|
808
|
-
});
|
|
809
1770
|
}
|
|
810
1771
|
|
|
811
1772
|
// src/commands/payouts.ts
|
|
812
1773
|
function registerPayoutCommands(program2) {
|
|
813
1774
|
const payouts = program2.command("payouts").description("Manage payouts");
|
|
814
|
-
payouts.command("list").description("List payouts").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option(
|
|
1775
|
+
payouts.command("list").description("List payouts").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option(
|
|
1776
|
+
"--status <status>",
|
|
1777
|
+
"Filter by status (pending, processing, completed, failed, cancelled)"
|
|
1778
|
+
).option("--affiliate-id <id>", "Filter by affiliate ID").option("--sort <field:dir>", "Sort").option("--date-from <date>", "Filter from date").option("--date-to <date>", "Filter to date").action(async function() {
|
|
815
1779
|
const o = opts(this);
|
|
816
1780
|
try {
|
|
817
1781
|
const client = await getClient(o);
|
|
@@ -824,7 +1788,14 @@ function registerPayoutCommands(program2) {
|
|
|
824
1788
|
dateFrom: o.dateFrom,
|
|
825
1789
|
dateTo: o.dateTo
|
|
826
1790
|
});
|
|
827
|
-
output(result, o, [
|
|
1791
|
+
output(result, o, [
|
|
1792
|
+
"id",
|
|
1793
|
+
"affiliate_id",
|
|
1794
|
+
"amount",
|
|
1795
|
+
"status",
|
|
1796
|
+
"payment_method",
|
|
1797
|
+
"created_at"
|
|
1798
|
+
]);
|
|
828
1799
|
} catch (err) {
|
|
829
1800
|
handleError(err, o.json);
|
|
830
1801
|
}
|
|
@@ -868,7 +1839,7 @@ function registerProgramCommands(program2) {
|
|
|
868
1839
|
handleError(err, o.json);
|
|
869
1840
|
}
|
|
870
1841
|
});
|
|
871
|
-
prog.command("update").description("Update program settings").option("--name <name>", "Program name").option("--tagline <text>", "Tagline").option("--category <cat>", "Category").option("--description <text>", "Description").option("--website-url <url>", "Website URL").option("--logo-url <url>", "Logo URL").option("--
|
|
1842
|
+
prog.command("update").description("Update program settings").option("--name <name>", "Program name").option("--tagline <text>", "Tagline").option("--category <cat>", "Category").option("--description <text>", "Description").option("--website-url <url>", "Website URL").option("--logo-url <url>", "Logo URL").option("--access-mode <mode>", "Access mode: PUBLIC, PRIVATE, or INVITE").option("--affiliate-links-enabled", "Enable affiliate links").option("--no-affiliate-links-enabled", "Disable affiliate links").action(async function() {
|
|
872
1843
|
const o = opts(this);
|
|
873
1844
|
try {
|
|
874
1845
|
const client = await getClient(o);
|
|
@@ -879,7 +1850,7 @@ function registerProgramCommands(program2) {
|
|
|
879
1850
|
if (o.description !== void 0) params.description = o.description;
|
|
880
1851
|
if (o.websiteUrl !== void 0) params.website_url = o.websiteUrl;
|
|
881
1852
|
if (o.logoUrl !== void 0) params.logo_url = o.logoUrl;
|
|
882
|
-
if (o.
|
|
1853
|
+
if (o.accessMode !== void 0) params.access_mode = o.accessMode;
|
|
883
1854
|
if (o.affiliateLinksEnabled !== void 0)
|
|
884
1855
|
params.affiliate_links_enabled = o.affiliateLinksEnabled;
|
|
885
1856
|
const result = await client.program.update(params);
|
|
@@ -1021,7 +1992,8 @@ function registerFraudRules(prog) {
|
|
|
1021
1992
|
if (o.selfReferral !== void 0) params.self_referral = o.selfReferral;
|
|
1022
1993
|
if (o.duplicateIp !== void 0) params.duplicate_ip = o.duplicateIp;
|
|
1023
1994
|
if (o.vpnProxy !== void 0) params.vpn_proxy = o.vpnProxy;
|
|
1024
|
-
if (o.suspiciousConversion !== void 0)
|
|
1995
|
+
if (o.suspiciousConversion !== void 0)
|
|
1996
|
+
params.suspicious_conversion = o.suspiciousConversion;
|
|
1025
1997
|
const result = await client.program.fraudRules.update(params);
|
|
1026
1998
|
output(result, o);
|
|
1027
1999
|
} catch (err) {
|
|
@@ -1053,10 +2025,8 @@ function registerPortal(prog) {
|
|
|
1053
2025
|
if (o.customDomain !== void 0) params.custom_domain = o.customDomain;
|
|
1054
2026
|
if (o.termsUrl !== void 0) params.terms_url = o.termsUrl;
|
|
1055
2027
|
if (o.privacyUrl !== void 0) params.privacy_url = o.privacyUrl;
|
|
1056
|
-
if (o.onboardingEnabled !== void 0)
|
|
1057
|
-
|
|
1058
|
-
if (o.resourcesEnabled !== void 0)
|
|
1059
|
-
params.resources_enabled = o.resourcesEnabled;
|
|
2028
|
+
if (o.onboardingEnabled !== void 0) params.onboarding_enabled = o.onboardingEnabled;
|
|
2029
|
+
if (o.resourcesEnabled !== void 0) params.resources_enabled = o.resourcesEnabled;
|
|
1060
2030
|
const result = await client.program.portal.update(params);
|
|
1061
2031
|
output(result, o);
|
|
1062
2032
|
} catch (err) {
|
|
@@ -1099,7 +2069,14 @@ function registerGroups(prog) {
|
|
|
1099
2069
|
const result = await client.program.groups.list({
|
|
1100
2070
|
expand: o.expand
|
|
1101
2071
|
});
|
|
1102
|
-
output(result, o, [
|
|
2072
|
+
output(result, o, [
|
|
2073
|
+
"id",
|
|
2074
|
+
"name",
|
|
2075
|
+
"description",
|
|
2076
|
+
"is_default",
|
|
2077
|
+
"affiliate_count",
|
|
2078
|
+
"created_at"
|
|
2079
|
+
]);
|
|
1103
2080
|
} catch (err) {
|
|
1104
2081
|
handleError(err, o.json);
|
|
1105
2082
|
}
|
|
@@ -1230,51 +2207,53 @@ function registerCreatives(prog) {
|
|
|
1230
2207
|
});
|
|
1231
2208
|
}
|
|
1232
2209
|
|
|
1233
|
-
// src/commands/
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
marketplace.command("list").description("List marketplace programs").option("--limit <n>", "Items per page", "50").option("--page <n>", "Page number", "1").option("--category <cat>", "Filter by category").option("--search <query>", "Search programs").option("--sort <field:dir>", "Sort").action(async function() {
|
|
2210
|
+
// src/commands/referrals.ts
|
|
2211
|
+
function registerReferralCommands(program2) {
|
|
2212
|
+
const referrals = program2.command("referrals").description("Manage referrals");
|
|
2213
|
+
referrals.command("list").description("List referrals").option("--limit <n>", "Items per page", "50").option("--starting-after <id>", "Cursor: fetch items after this ID").option("--ending-before <id>", "Cursor: fetch items before this ID").option("--affiliate-id <id>", "Filter by affiliate ID").option("--status <status>", "Filter by status").option("--order <dir>", "Order (asc, desc)").option("--expand <fields>", "Expand fields").option("--created-gte <date>", "Created after date").option("--created-lte <date>", "Created before date").action(async function() {
|
|
1238
2214
|
const o = opts(this);
|
|
1239
2215
|
try {
|
|
1240
|
-
const
|
|
1241
|
-
const
|
|
1242
|
-
const result = await client.marketplace.list({
|
|
2216
|
+
const client = await getClient(o);
|
|
2217
|
+
const result = await client.referrals.list({
|
|
1243
2218
|
limit: Number(o.limit),
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
2219
|
+
starting_after: o.startingAfter,
|
|
2220
|
+
ending_before: o.endingBefore,
|
|
2221
|
+
affiliate_id: o.affiliateId,
|
|
2222
|
+
status: o.status,
|
|
2223
|
+
order: o.order,
|
|
2224
|
+
expand: o.expand,
|
|
2225
|
+
created_gte: o.createdGte,
|
|
2226
|
+
created_lte: o.createdLte
|
|
1248
2227
|
});
|
|
1249
|
-
output(result, o, ["id", "
|
|
2228
|
+
output(result, o, ["id", "affiliate_id", "email", "status", "created_at"]);
|
|
1250
2229
|
} catch (err) {
|
|
1251
2230
|
handleError(err, o.json);
|
|
1252
2231
|
}
|
|
1253
2232
|
});
|
|
1254
|
-
|
|
2233
|
+
referrals.command("get <id>").description("Get a referral by ID").option("--expand <fields>", "Expand fields").option("--include <fields>", "Include fields").action(async function(id) {
|
|
1255
2234
|
const o = opts(this);
|
|
1256
2235
|
try {
|
|
1257
|
-
const
|
|
1258
|
-
const
|
|
1259
|
-
|
|
2236
|
+
const client = await getClient(o);
|
|
2237
|
+
const result = await client.referrals.retrieve(id, {
|
|
2238
|
+
expand: o.expand,
|
|
2239
|
+
include: o.include
|
|
2240
|
+
});
|
|
1260
2241
|
output(result, o);
|
|
1261
2242
|
} catch (err) {
|
|
1262
2243
|
handleError(err, o.json);
|
|
1263
2244
|
}
|
|
1264
2245
|
});
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
// src/commands/embed-tokens.ts
|
|
1268
|
-
function registerEmbedTokenCommands(program2) {
|
|
1269
|
-
const embedTokens = program2.command("embed-tokens").description("Generate embed tokens");
|
|
1270
|
-
embedTokens.command("create").description("Create an embed token").option("--affiliate-id <id>", "Affiliate ID").option("--external-user-id <id>", "External user ID").option("--email <email>", "Partner email").option("--name <name>", "Partner name").action(async function() {
|
|
2246
|
+
referrals.command("create").description("Create a referral").requiredOption("--email <email>", "Referral email").requiredOption("--affiliate-id <id>", "Affiliate ID").option("--subscription-id <id>", "Subscription ID").option("--customer-id <id>", "Customer ID").option("--click-id <id>", "Click ID").option("--status <status>", "Initial status").option("--name <name>", "Referral name").action(async function() {
|
|
1271
2247
|
const o = opts(this);
|
|
1272
2248
|
try {
|
|
1273
2249
|
const client = await getClient(o);
|
|
1274
|
-
const result = await client.
|
|
1275
|
-
affiliate_id: o.affiliateId,
|
|
1276
|
-
external_user_id: o.externalUserId,
|
|
2250
|
+
const result = await client.referrals.create({
|
|
1277
2251
|
email: o.email,
|
|
2252
|
+
affiliate_id: o.affiliateId,
|
|
2253
|
+
subscription_id: o.subscriptionId,
|
|
2254
|
+
customer_id: o.customerId,
|
|
2255
|
+
click_id: o.clickId,
|
|
2256
|
+
status: o.status,
|
|
1278
2257
|
name: o.name
|
|
1279
2258
|
});
|
|
1280
2259
|
output(result, o);
|
|
@@ -1282,50 +2261,28 @@ function registerEmbedTokenCommands(program2) {
|
|
|
1282
2261
|
handleError(err, o.json);
|
|
1283
2262
|
}
|
|
1284
2263
|
});
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
// src/commands/login.ts
|
|
1288
|
-
function registerLoginCommand(program2) {
|
|
1289
|
-
program2.command("login").description("Log in via browser (OAuth 2.1)").action(async function() {
|
|
2264
|
+
referrals.command("update <id>").description("Update a referral").option("--email <email>", "Referral email").option("--status <status>", "Status").option("--subscription-id <id>", "Subscription ID").option("--customer-id <id>", "Customer ID").option("--name <name>", "Referral name").action(async function(id) {
|
|
1290
2265
|
const o = opts(this);
|
|
1291
2266
|
try {
|
|
1292
|
-
const
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
2267
|
+
const client = await getClient(o);
|
|
2268
|
+
const params = {};
|
|
2269
|
+
if (o.email !== void 0) params.email = o.email;
|
|
2270
|
+
if (o.status !== void 0) params.status = o.status;
|
|
2271
|
+
if (o.subscriptionId !== void 0) params.subscription_id = o.subscriptionId;
|
|
2272
|
+
if (o.customerId !== void 0) params.customer_id = o.customerId;
|
|
2273
|
+
if (o.name !== void 0) params.name = o.name;
|
|
2274
|
+
const result = await client.referrals.update(id, params);
|
|
2275
|
+
output(result, o);
|
|
1300
2276
|
} catch (err) {
|
|
1301
2277
|
handleError(err, o.json);
|
|
1302
2278
|
}
|
|
1303
2279
|
});
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
// src/commands/logout.ts
|
|
1307
|
-
function registerLogoutCommand(program2) {
|
|
1308
|
-
program2.command("logout").description("Log out and remove stored credentials").action(async function() {
|
|
2280
|
+
referrals.command("delete <id>").description("Delete a referral").action(async function(id) {
|
|
1309
2281
|
const o = opts(this);
|
|
1310
2282
|
try {
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
const issuer = baseUrl.replace(/\/v1\/?$/, "");
|
|
1315
|
-
try {
|
|
1316
|
-
await fetch(`${issuer}/oauth/revoke`, {
|
|
1317
|
-
method: "POST",
|
|
1318
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1319
|
-
body: new URLSearchParams({
|
|
1320
|
-
token: auth.access_token,
|
|
1321
|
-
client_id: CLIENT_ID
|
|
1322
|
-
})
|
|
1323
|
-
});
|
|
1324
|
-
} catch {
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
clearAuth();
|
|
1328
|
-
console.log("Logged out.");
|
|
2283
|
+
const client = await getClient(o);
|
|
2284
|
+
const result = await client.referrals.del(id);
|
|
2285
|
+
outputSuccess(result.message ?? "Referral deleted.", o);
|
|
1329
2286
|
} catch (err) {
|
|
1330
2287
|
handleError(err, o.json);
|
|
1331
2288
|
}
|
|
@@ -1363,58 +2320,10 @@ function registerWhoamiCommand(program2) {
|
|
|
1363
2320
|
});
|
|
1364
2321
|
}
|
|
1365
2322
|
|
|
1366
|
-
// src/commands/config.ts
|
|
1367
|
-
var VALID_KEYS = ["api-key", "base-url"];
|
|
1368
|
-
var KEY_MAP = {
|
|
1369
|
-
"api-key": "api_key",
|
|
1370
|
-
"base-url": "base_url"
|
|
1371
|
-
};
|
|
1372
|
-
function registerConfigCommands(program2) {
|
|
1373
|
-
const config = program2.command("config").description("Manage CLI configuration");
|
|
1374
|
-
config.command("get <key>").description("Get a config value (api-key, base-url)").action(async function(key) {
|
|
1375
|
-
const o = opts(this);
|
|
1376
|
-
try {
|
|
1377
|
-
if (!VALID_KEYS.includes(key)) {
|
|
1378
|
-
console.error(`Unknown config key: ${key}. Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
1379
|
-
process.exit(1);
|
|
1380
|
-
}
|
|
1381
|
-
const stored = loadConfig();
|
|
1382
|
-
const mappedKey = KEY_MAP[key];
|
|
1383
|
-
const value = stored[mappedKey];
|
|
1384
|
-
if (value) {
|
|
1385
|
-
if (key === "api-key") {
|
|
1386
|
-
const v = value;
|
|
1387
|
-
console.log(`${v.slice(0, 10)}...${v.slice(-4)}`);
|
|
1388
|
-
} else {
|
|
1389
|
-
console.log(value);
|
|
1390
|
-
}
|
|
1391
|
-
} else {
|
|
1392
|
-
console.log(`${key} is not set.`);
|
|
1393
|
-
}
|
|
1394
|
-
} catch (err) {
|
|
1395
|
-
handleError(err, o.json);
|
|
1396
|
-
}
|
|
1397
|
-
});
|
|
1398
|
-
config.command("set <key> <value>").description("Set a config value (api-key, base-url)").action(async function(key, value) {
|
|
1399
|
-
const o = opts(this);
|
|
1400
|
-
try {
|
|
1401
|
-
if (!VALID_KEYS.includes(key)) {
|
|
1402
|
-
console.error(`Unknown config key: ${key}. Valid keys: ${VALID_KEYS.join(", ")}`);
|
|
1403
|
-
process.exit(1);
|
|
1404
|
-
}
|
|
1405
|
-
const mappedKey = KEY_MAP[key];
|
|
1406
|
-
saveConfig({ [mappedKey]: value });
|
|
1407
|
-
console.log(`${key} saved.`);
|
|
1408
|
-
} catch (err) {
|
|
1409
|
-
handleError(err, o.json);
|
|
1410
|
-
}
|
|
1411
|
-
});
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
2323
|
// src/cli.ts
|
|
1415
2324
|
function createProgram() {
|
|
1416
2325
|
const program2 = new import_commander.Command();
|
|
1417
|
-
program2.name("affonso").description("Affonso CLI \u2014 manage your affiliate program from the terminal").version(
|
|
2326
|
+
program2.name("affonso").description("Affonso CLI \u2014 manage your affiliate program from the terminal").version(package_default.version).option("--json", "Output as JSON").option("--api-key <key>", "API key for this request").option("--base-url <url>", "Custom API base URL").option("--no-color", "Disable colored output");
|
|
1418
2327
|
registerLoginCommand(program2);
|
|
1419
2328
|
registerLogoutCommand(program2);
|
|
1420
2329
|
registerWhoamiCommand(program2);
|